From 0e148db13197450aa314a77af0bed3571de94254 Mon Sep 17 00:00:00 2001 From: Konnor Rogers Date: Mon, 6 Jul 2020 15:24:18 -0400 Subject: [PATCH] Feature/yard documentation (#85) * Add yard as a dev dependency, and create a rake task * add .yardoc to gitignore, remove doc generation * add .yardoc to gitignore * remove yard from gemspec, add to base Gemfile * modify rakefile' * allow user to specify port * document configurable public methods with Yard * finished with content module * Add documentation to all 'concerns/site' * accidentally removed collections method * remove custom cache dir * fix linting issues * Fix an issue with return values. * docs: fix changes discussed in PR review. * docs: fix linting issue --- .gitignore | 1 + Gemfile | 2 +- bridgetown-core/Rakefile | 14 +++ .../concerns/site/configurable.rb | 93 +++++++++----- .../bridgetown-core/concerns/site/content.rb | 117 +++++++++++++----- .../concerns/site/extensible.rb | 27 ++-- .../concerns/site/processable.rb | 22 ++-- .../concerns/site/renderable.rb | 24 +++- .../bridgetown-core/concerns/site/writable.rb | 18 ++- 9 files changed, 231 insertions(+), 87 deletions(-) diff --git a/.gitignore b/.gitignore index 93051c9ff..7ef6c62e8 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,4 @@ bbin/ */test/dest */tmp/* .vscode +.yardoc diff --git a/Gemfile b/Gemfile index cc6859c41..9eee6b6ba 100644 --- a/Gemfile +++ b/Gemfile @@ -33,7 +33,7 @@ end group :bridgetown_optional_dependencies do gem "mime-types", "~> 3.0" - gem "rdoc", "~> 6.0" + gem "yard", "~> 0.9" gem "tomlrb", "~> 1.2" gem "classifier-reborn", "~> 2.2" gem "liquid-c", "~> 4.0" diff --git a/bridgetown-core/Rakefile b/bridgetown-core/Rakefile index 41fee08b4..cd82344c1 100644 --- a/bridgetown-core/Rakefile +++ b/bridgetown-core/Rakefile @@ -12,3 +12,17 @@ Rake::TestTask.new(:test) do |test| test.pattern = "test/**/test_*.rb" test.verbose = true end + +require 'yard' +YARD::Rake::YardocTask.new(:yard) do |t| + t.files = ['lib/**/*.rb'] + t.options = ['--no-output'] + t.stats_options = ['--list-undoc'] +end + +namespace :yard do + task :serve do + port = ENV['YARD_PORT'] || "8808" + sh("yard server --reload -p #{port}") + end +end diff --git a/bridgetown-core/lib/bridgetown-core/concerns/site/configurable.rb b/bridgetown-core/lib/bridgetown-core/concerns/site/configurable.rb index e150c2f9f..2dfca39e9 100644 --- a/bridgetown-core/lib/bridgetown-core/concerns/site/configurable.rb +++ b/bridgetown-core/lib/bridgetown-core/concerns/site/configurable.rb @@ -2,12 +2,17 @@ module Bridgetown module Site::Configurable - # Public: Set the site's configuration. This handles side-effects caused by + # Set the site's configuration. This handles side-effects caused by # changing values in the configuration. # - # config - a Bridgetown::Configuration, containing the new configuration. + # @param config [Bridgetown::Configuration] + # An instance of {Bridgetown::Configuration}, + # containing the new configuration. # - # Returns the new configuration. + # @return [Bridgetown::Configuration] + # A new instance of {Bridgetown::Configuration} + # + # @see Bridgetown::Configuration def config=(config) @config = config.clone @@ -32,81 +37,107 @@ def config=(config) @config end - # Returns the FrontmatterDefaults or creates a new FrontmatterDefaults - # if it doesn't already exist. + # Returns the current instance of {FrontmatterDefaults} or + # creates a new instance {FrontmatterDefaults} if it doesn't already exist. # - # Returns The FrontmatterDefaults + # @return [FrontmatterDefaults] + # Returns an instance of {FrontmatterDefaults} def frontmatter_defaults @frontmatter_defaults ||= FrontmatterDefaults.new(self) end - # Whether to perform a full rebuild without incremental regeneration + # Whether to perform a full rebuild without incremental regeneration. + # If either +override+["incremental"] or +config+["incremental"] are true, + # fully rebuild the site. If not, incrementally build the site. # - # Returns a Boolean: true for a full rebuild, false for normal build + # @param [Hash] override + # An override hash to override the current config value + # @option override [Boolean] "incremental" Whether to incrementally build + # @return [Boolean] true for full rebuild, false for normal build def incremental?(override = {}) override["incremental"] || config["incremental"] end - # Returns the publisher or creates a new publisher if it doesn't - # already exist. + # Returns the current instance of {Publisher} or creates a new instance of + # {Publisher} if one doesn't exist. # - # Returns The Publisher + # @return [Publisher] Returns an instance of {Publisher} def publisher @publisher ||= Publisher.new(self) end - # Public: Prefix a given path with the root directory. + # Prefix a path or paths with the {#root_dir} directory. # - # paths - (optional) path elements to a file or directory within the - # root directory + # @see Bridgetown.sanitized_path + # @param paths [Array] + # An array of paths to prefix with the root_dir directory using the + # {Bridgetown.sanitized_path} method. # - # Returns a path which is prefixed with the root_dir directory. + # @return [Array] Return an array of updated paths if multiple paths given. def in_root_dir(*paths) paths.reduce(root_dir) do |base, path| Bridgetown.sanitized_path(base, path) end end - # Public: Prefix a given path with the source directory. - # - # paths - (optional) path elements to a file or directory within the - # source directory + # Prefix a path or paths with the {#source} directory. # - # Returns a path which is prefixed with the source directory. + # @see Bridgetown.sanitized_path + # @param paths [Array] + # An array of paths to prefix with the source directory using the + # {Bridgetown.sanitized_path} method. + # @return [Array] Return an array of updated paths if multiple paths given. def in_source_dir(*paths) paths.reduce(source) do |base, path| Bridgetown.sanitized_path(base, path) end end - # Public: Prefix a given path with the destination directory. + # Prefix a path or paths with the {#dest} directory. # - # paths - (optional) path elements to a file or directory within the - # destination directory + # @see Bridgetown.sanitized_path + # @param paths [Array] + # An array of paths to prefix with the destination directory using the + # {Bridgetown.sanitized_path} method. # - # Returns a path which is prefixed with the destination directory. + # @return [Array] Return an array of updated paths if multiple paths given. def in_dest_dir(*paths) paths.reduce(dest) do |base, path| Bridgetown.sanitized_path(base, path) end end - # Public: Prefix a given path with the cache directory. + # Prefix a path or paths with the {#cache_dir} directory. # - # paths - (optional) path elements to a file or directory within the - # cache directory + # @see Bridgetown.sanitized_path + # @param paths [Array] + # An array of paths to prefix with the {#cache_dir} directory using the + # {Bridgetown.sanitized_path} method. # - # Returns a path which is prefixed with the cache directory. + # @return [Array] Return an array of updated paths if multiple paths given. def in_cache_dir(*paths) paths.reduce(cache_dir) do |base, path| Bridgetown.sanitized_path(base, path) end end - # Public: The full path to the directory that houses all the collections registered - # with the current site. + # The full path to the directory that houses all the registered collections + # for the current site. + # + # If +@collections_path+ is specified use its value. + # + # If +@collections+ is not specified and +config+["collections_dir"] is + # specified, prepend it with {#source} and assign it to + # {#collections_path}. + # + # If +@collections+ is not specified and +config+["collections_dir"] is not + # specified, assign {#source} to +@collections_path+ # - # Returns the source directory or the absolute path to the custom collections_dir + # @return [String] Returns the full path to the collections directory + # @see #config + # @see #source + # @see #collections_path + # @see #in_source_dir def collections_path dir_str = config["collections_dir"] @collections_path ||= dir_str.empty? ? source : in_source_dir(dir_str) diff --git a/bridgetown-core/lib/bridgetown-core/concerns/site/content.rb b/bridgetown-core/lib/bridgetown-core/concerns/site/content.rb index bf24970ea..fbcb02b5a 100644 --- a/bridgetown-core/lib/bridgetown-core/concerns/site/content.rb +++ b/bridgetown-core/lib/bridgetown-core/concerns/site/content.rb @@ -4,17 +4,24 @@ module Bridgetown module Site::Content # Construct a Hash of Posts indexed by the specified Post attribute. # - # post_attr - The String name of the Post attribute. + # @param post_attr [String] The String name of the Post attribute. # - # Examples + # @example + # Returns a hash like so: { attr => posts } where + # + # attr - One of the values for the requested attribute. + # + # posts - The Array of Posts with the given attr value. + # + # @example # # post_attr_hash('categories') # # => { 'tech' => [, ], # # 'ruby' => [] } # - # Returns the Hash: { attr => posts } where - # attr - One of the values for the requested attribute. - # posts - The Array of Posts with the given attr value. + # @return [Hash{String, Symbol => Array}] + # Returns a hash of !{attr => posts} + # def post_attr_hash(post_attr) # Build a hash map based on the specified post attribute ( post attr => # array of posts ) then sort each array in reverse order. @@ -28,41 +35,85 @@ def post_attr_hash(post_attr) end end + # Returns a hash of "tags" using {#post_attr_hash} where each tag is a key + # and each value is a post which contains the key. + # @example + # tags + # # => { 'tech': [, ], + # # 'ruby': [ } + # @return [Hash{String, Array}] Returns a hash of all tags and their corresponding posts + # @see post_attr_hash def tags post_attr_hash("tags") end + # Returns a hash of "categories" using {#post_attr_hash} where each tag is + # a key and each value is a post which contains the key. + # @example + # categories + # # => { 'tech': [, ], + # # 'ruby': [ } + # @return [Hash{String, Array}] Returns a hash of all categories and + # their corresponding posts + # @see post_attr_hash def categories post_attr_hash("categories") end + # Returns the value of +data+["site_metadata"] or creates a new instance of + # +ActiveSupport::HashWithIndifferentAccess+ + # @return [Hash] Returns a hash of site metadata def metadata data["site_metadata"] ||= ActiveSupport::HashWithIndifferentAccess.new end # The Hash payload containing site-wide data. # - # Returns the Hash: { "site" => data } where data is a Hash with keys: - # "time" - The Time as specified in the configuration or the - # current time if none was specified. - # "posts" - The Array of Posts, sorted chronologically by post date - # and then title. - # "pages" - The Array of all Pages. - # "html_pages" - The Array of HTML Pages. - # "categories" - The Hash of category values and Posts. - # See Site#post_attr_hash for type info. - # "tags" - The Hash of tag values and Posts. - # See Site#post_attr_hash for type info. + # @example + # site_payload + # # => { "site" => data } Where data is a Hash. See example below + # + # site = site_payload["site"] + # # => Returns a Hash with the following keys: + # # + # # site["time"] - The Time as specified in the configuration or the + # # current time if none was specified. + # # + # # site["posts"] - The Array of Posts, sorted chronologically by post date + # # and then title. + # # + # # site["pages"] - The Array of all Pages. + # # + # # site["html_pages"] - The Array of HTML Pages. + # # + # # site["categories"] - The Hash of category values and Posts. + # # See Site#post_attr_hash for type info. + # # + # # site["tags"] - The Hash of tag values and Posts. + # # See Site#post_attr_hash for type info. + # + # @return [Hash] Returns a hash in the structure of { "site" => data } + # + # See above example for usage. + # + # @see #post_attr_hash def site_payload Drops::UnifiedPayloadDrop.new self end alias_method :to_liquid, :site_payload - # The list of collections and their corresponding Bridgetown::Collection instances. - # If config['collections'] is set, a new instance is created - # for each item in the collection, a new hash is returned otherwise. + # The list of {#collections} and their corresponding {Bridgetown::Collection} instances. + # + # If +config+['collections'] is set, a new instance of {Bridgetown::Collection} is created + # for each entry in the collections configuration. + # + # If +config+["collections"] is not specified, a blank hash is returned. # - # Returns a Hash containing collection name-to-instance pairs. + # @return [Hash{String, Symbol => Bridgetown::Collection}] A Hash + # containing a collection name-to-instance pairs. + # + # @return [Hash] Returns a blank hash if no items found + # @see Collection def collections @collections ||= collection_names.each_with_object( ActiveSupport::HashWithIndifferentAccess.new @@ -71,10 +122,11 @@ def collections end end - # The list of collection names. - # - # Returns an array of collection names from the configuration, - # or an empty array if the `collections` key is not set. + # An array of collection names. + # @return [Array] an array of collection names from the configuration, + # or an empty array if the +config+["collections"] key is not set. + # @raise ArgumentError Raise an error if +config+["collections"] is not + # an Array or a Hash def collection_names case config["collections"] when Hash @@ -88,22 +140,29 @@ def collection_names end end - # Get all the documents - # - # Returns an Array of all Documents + # Get all documents. + # @return [Array] an array of documents from the configuration def documents collections.each_with_object(Set.new) do |(_, collection), set| set.merge(collection.docs).merge(collection.files) end.to_a end - # Get the to be written documents + # Get the documents to be written # - # Returns an Array of Documents which should be written + # @return [Array] an Array of Documents which should be written and + # that +respond_to :write?+ + # @see #documents + # @see Collection def docs_to_write documents.select(&:write?) end + # Get all posts. + # + # @return [Collection] A #Collection of posts. Returns +#collections+["posts"] + # @return [Collection] Return a new #Collection if +#collections+["posts"] is nil + # @see Collection def posts collections["posts"] ||= Collection.new(self, "posts") end diff --git a/bridgetown-core/lib/bridgetown-core/concerns/site/extensible.rb b/bridgetown-core/lib/bridgetown-core/concerns/site/extensible.rb index 70e33c4b8..cc7f4ac3f 100644 --- a/bridgetown-core/lib/bridgetown-core/concerns/site/extensible.rb +++ b/bridgetown-core/lib/bridgetown-core/concerns/site/extensible.rb @@ -3,17 +3,19 @@ module Bridgetown module Site::Extensible # Load necessary libraries, plugins, converters, and generators. - # - # Returns nothing. + # @see Bridgetown::Converter + # @see Bridgetown::Generator + # @see PluginManager + # @return [void] def setup plugin_manager.require_plugin_files self.converters = instantiate_subclasses(Bridgetown::Converter) self.generators = instantiate_subclasses(Bridgetown::Generator) end - # Run each of the Generators. - # - # Returns nothing. + # Run all Generators. + # @see Bridgetown::Generator + # @return [void] def generate generators.each do |generator| start = Time.now @@ -32,8 +34,9 @@ def generate end # Get the implementation class for the given Converter. - # Returns the Converter instance implementing the given Converter. - # klass - The Class of the Converter to fetch. + # @param klass [Object] The Class of the Converter to fetch. + # @return [Bridgetown::Converter] Returns the {Bridgetown::Converter} + # instance implementing the given +Converter+. def find_converter_instance(klass) @find_converter_instance ||= {} @find_converter_instance[klass] ||= begin @@ -42,11 +45,11 @@ def find_converter_instance(klass) end end - # klass - class or module containing the subclasses. - # Returns array of instances of subclasses of parameter. - # Create array of instances of the subclasses of the class or module - # passed in as argument. - + # Create an array of instances of the subclasses of the class or module + # passed in as argument. + # @param klass [Class, Module] - class or module containing the subclasses. + # @return [Array] Returns an array of instances of subclasses of + # +klass+. def instantiate_subclasses(klass) klass.descendants.sort.map do |c| c.new(config) diff --git a/bridgetown-core/lib/bridgetown-core/concerns/site/processable.rb b/bridgetown-core/lib/bridgetown-core/concerns/site/processable.rb index 1fabd7403..1b795a484 100644 --- a/bridgetown-core/lib/bridgetown-core/concerns/site/processable.rb +++ b/bridgetown-core/lib/bridgetown-core/concerns/site/processable.rb @@ -2,9 +2,14 @@ module Bridgetown module Site::Processable - # Public: Read, process, and write this Site to output. - # - # Returns nothing. + # Reset, Read, Generate, Render, Cleanup, Process, and Write this Site to output. + # @return [void] + # @see #reset + # @see #read + # @see #generate + # @see #render + # @see #cleanup + # @see #write def process reset read @@ -16,10 +21,9 @@ def process end # rubocop:disable Metrics/AbcSize - # + # Reset Site details. - # - # Returns nothing + # @return [void] def reset self.time = if config["time"] Utils.parse_date(config["time"].to_s, "Invalid time in bridgetown.config.yml.") @@ -43,11 +47,11 @@ def reset Bridgetown::Cache.clear_if_config_changed config Bridgetown::Hooks.trigger :site, :after_reset, self end + # rubocop:enable Metrics/AbcSize # Read Site data from disk and load it into internal data structures. - # - # Returns nothing. + # @return [void] def read Bridgetown::Hooks.trigger :site, :pre_read, self reader.read @@ -58,8 +62,6 @@ def read private # Limits the current posts; removes the posts which exceed the limit_posts - # - # Returns nothing def limit_posts! if limit_posts.positive? limit = posts.docs.length < limit_posts ? posts.docs.length : limit_posts diff --git a/bridgetown-core/lib/bridgetown-core/concerns/site/renderable.rb b/bridgetown-core/lib/bridgetown-core/concerns/site/renderable.rb index 5dd91d732..5bb580476 100644 --- a/bridgetown-core/lib/bridgetown-core/concerns/site/renderable.rb +++ b/bridgetown-core/lib/bridgetown-core/concerns/site/renderable.rb @@ -3,8 +3,7 @@ module Bridgetown module Site::Renderable # Render the site to the destination. - # - # Returns nothing. + # @return [void] def render payload = site_payload @@ -18,6 +17,14 @@ def render Bridgetown::Hooks.trigger :site, :post_render, self, payload end + # Executes inline Ruby frontmatter if + # +ENV+["BRIDGETOWN_RUBY_IN_FRONTMATTER"] equals "true" + # + # @example + # calculation: !ruby/string:Rb | + # [2 * 4, 5 + 2].min + # @return [void] + # @see https://www.bridgetownrb.com/docs/front-matter#ruby-front-matter def execute_inline_ruby_for_layouts! return unless config.should_execute_inline_ruby? @@ -26,6 +33,10 @@ def execute_inline_ruby_for_layouts! end end + # Renders all documents + # @param payload [Hash] A hash of site data. + # @return [void] + # @see Bridgetown::Site::Content#site_payload def render_docs(payload) collections.each_value do |collection| collection.docs.each do |document| @@ -34,12 +45,21 @@ def render_docs(payload) end end + # Renders all pages + # @param payload [Hash] A hash of site data. + # @return [void] + # @see Bridgetown::Site::Content#site_payload def render_pages(payload) pages.each do |page| render_regenerated(page, payload) end end + # Regenerates a site using {Bridgetown::Renderer} + # @param document [Post] The document to regenerate. + # @param payload [Hash] A hash of site data. + # @return [void] + # @see Bridgetown::Renderer def render_regenerated(document, payload) return unless regenerator.regenerate?(document) diff --git a/bridgetown-core/lib/bridgetown-core/concerns/site/writable.rb b/bridgetown-core/lib/bridgetown-core/concerns/site/writable.rb index 9c6cded2e..7c9439c56 100644 --- a/bridgetown-core/lib/bridgetown-core/concerns/site/writable.rb +++ b/bridgetown-core/lib/bridgetown-core/concerns/site/writable.rb @@ -4,14 +4,14 @@ module Bridgetown module Site::Writable # Remove orphaned files and empty directories in destination. # - # Returns nothing. + # @return [void] def cleanup @cleaner.cleanup! end # Write static files, pages, and posts. # - # Returns nothing. + # @return [void] def write each_site_file do |item| item.write(dest) if regenerator.regenerate?(item) @@ -20,6 +20,20 @@ def write Bridgetown::Hooks.trigger :site, :post_write, self end + # Yields the pages from {#pages}, {#static_files}, and {#docs_to_write}. + # + # @yieldparam item [Document, Page, StaticFile] Yields a + # {#Bridgetown::Page}, {#Bridgetown::StaticFile}, or + # {#Bridgetown::Document} object. + # + # @return [void] + # + # @see #pages + # @see #static_files + # @see #docs_to_write + # @see Page + # @see StaticFile + # @see Document def each_site_file %w(pages static_files docs_to_write).each do |type| send(type).each do |item|