Dynamically generate configuration docs using YARD (#968)
Dynamically generate configuration docs using YARD
This commit is contained in:
Родитель
e443c1f80a
Коммит
8682057f98
|
@ -0,0 +1 @@
|
|||
--plugin activesupport-concern
|
|
@ -6,6 +6,10 @@
|
|||
|
||||
*Joel Hawksley*
|
||||
|
||||
* Add documentation for configuration options.
|
||||
|
||||
*Joel Hawksley*
|
||||
|
||||
## 2.34.0
|
||||
|
||||
* Add the ability to enable ActiveSupport notifications (`!render.view_component` event) with `config.view_component.instrumentation_enabled`.
|
||||
|
|
|
@ -219,6 +219,8 @@ GEM
|
|||
xpath (3.2.0)
|
||||
nokogiri (~> 1.8)
|
||||
yard (0.9.26)
|
||||
yard-activesupport-concern (0.0.1)
|
||||
yard (>= 0.8)
|
||||
zeitwerk (2.4.2)
|
||||
|
||||
PLATFORMS
|
||||
|
@ -241,6 +243,7 @@ DEPENDENCIES
|
|||
slim (~> 4.0)
|
||||
view_component!
|
||||
yard (~> 0.9.25)
|
||||
yard-activesupport-concern
|
||||
|
||||
BUNDLED WITH
|
||||
2.2.20
|
||||
|
|
68
Rakefile
68
Rakefile
|
@ -3,6 +3,7 @@
|
|||
require "bundler/gem_tasks"
|
||||
require "rake/testtask"
|
||||
require "yard"
|
||||
require "yard/mattr_accessor_handler"
|
||||
|
||||
Rake::TestTask.new(:test) do |t|
|
||||
t.libs << "test"
|
||||
|
@ -50,13 +51,18 @@ namespace :docs do
|
|||
registry = YARD::RegistryStore.new
|
||||
registry.load!(".yardoc")
|
||||
|
||||
instance_methods = registry.get("ViewComponent::Base").meths.select { |method| method.scope != :class }
|
||||
instance_methods_to_document =
|
||||
instance_methods.select do |method|
|
||||
meths =
|
||||
registry.
|
||||
get("ViewComponent::Base").
|
||||
meths.
|
||||
select do |method|
|
||||
!method.tag(:private) &&
|
||||
method.path.include?("ViewComponent::Base") &&
|
||||
method.visibility == :public
|
||||
end
|
||||
end.sort_by { |method| method[:name] }
|
||||
|
||||
instance_methods_to_document = meths.select { |method| method.scope != :class }
|
||||
class_methods_to_document = meths.select { |method| method.scope == :class }
|
||||
|
||||
File.open("docs/api.md", "w") do |f|
|
||||
f.puts("---")
|
||||
|
@ -67,6 +73,31 @@ namespace :docs do
|
|||
f.puts("<!-- Warning: AUTO-GENERATED file, do not edit. Add code comments to your Ruby instead <3 -->")
|
||||
f.puts
|
||||
f.puts("# API")
|
||||
|
||||
f.puts
|
||||
f.puts("## Class methods")
|
||||
|
||||
class_methods_to_document.each do |method|
|
||||
suffix =
|
||||
if method.tag(:deprecated)
|
||||
" (Deprecated)"
|
||||
end
|
||||
|
||||
types = if method.tag(:return)&.types
|
||||
" → [#{method.tag(:return).types.join(',')}]"
|
||||
end
|
||||
|
||||
f.puts
|
||||
f.puts("### #{method.sep}#{method.signature.gsub('def ', '')}#{types}#{suffix}")
|
||||
f.puts
|
||||
f.puts(method.docstring)
|
||||
|
||||
if method.tag(:deprecated)
|
||||
f.puts
|
||||
f.puts("_#{method.tag(:deprecated).text}_")
|
||||
end
|
||||
end
|
||||
|
||||
f.puts
|
||||
f.puts("## Instance methods")
|
||||
|
||||
|
@ -90,6 +121,35 @@ namespace :docs do
|
|||
f.puts("_#{method.tag(:deprecated).text}_")
|
||||
end
|
||||
end
|
||||
|
||||
f.puts
|
||||
f.puts("## Configuration")
|
||||
|
||||
registry.
|
||||
get("ViewComponent::Base").
|
||||
meths.
|
||||
select { |method| method[:mattr_accessor] }.
|
||||
sort_by { |method| method[:name] }.
|
||||
each do |method|
|
||||
|
||||
suffix =
|
||||
if method.tag(:deprecated)
|
||||
" (Deprecated)"
|
||||
end
|
||||
|
||||
f.puts
|
||||
f.puts("### #{method.sep}#{method.name}#{suffix}")
|
||||
|
||||
if method.docstring.length > 0
|
||||
f.puts
|
||||
f.puts(method.docstring)
|
||||
end
|
||||
|
||||
if method.tag(:deprecated)
|
||||
f.puts
|
||||
f.puts("_#{method.tag(:deprecated).text}_")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
85
docs/api.md
85
docs/api.md
|
@ -7,6 +7,20 @@ title: API
|
|||
|
||||
# API
|
||||
|
||||
## Class methods
|
||||
|
||||
### .with_collection(collection, **args)
|
||||
|
||||
Render a component for each element in a collection ([documentation](/guide/collections)):
|
||||
|
||||
render(ProductsComponent.with_collection(@products, foo: :bar))
|
||||
|
||||
### .with_collection_parameter(parameter)
|
||||
|
||||
Set the parameter name used when rendering elements of a collection ([documentation](/guide/collections)):
|
||||
|
||||
with_collection_parameter :item
|
||||
|
||||
## Instance methods
|
||||
|
||||
### #_output_postamble → [String]
|
||||
|
@ -21,11 +35,7 @@ Called before rendering the component. Override to perform operations that depen
|
|||
|
||||
Called after rendering the component.
|
||||
|
||||
_Use `before_render` instead. Will be removed in v3.0.0._
|
||||
|
||||
### #render? → [Boolean]
|
||||
|
||||
Override to determine whether the ViewComponent should render.
|
||||
_Use `#before_render` instead. Will be removed in v3.0.0._
|
||||
|
||||
### #controller → [ActionController::Base]
|
||||
|
||||
|
@ -35,10 +45,71 @@ The current controller. Use sparingly as doing so introduces coupling that inhib
|
|||
|
||||
A proxy through which to access helpers. Use sparingly as doing so introduces coupling that inhibits encapsulation & reuse, often making testing difficult.
|
||||
|
||||
### #with_variant(variant) → [self]
|
||||
### #render? → [Boolean]
|
||||
|
||||
Use the provided variant instead of the one determined by the current request.
|
||||
Override to determine whether the ViewComponent should render.
|
||||
|
||||
### #request → [ActionDispatch::Request]
|
||||
|
||||
The current request. Use sparingly as doing so introduces coupling that inhibits encapsulation & reuse, often making testing difficult.
|
||||
|
||||
### #with_variant(variant) → [self]
|
||||
|
||||
Use the provided variant instead of the one determined by the current request.
|
||||
|
||||
## Configuration
|
||||
|
||||
### #default_preview_layout
|
||||
|
||||
Set a custom default layout used for preview index and individual previews:
|
||||
|
||||
config.view_component.default_preview_layout = "component_preview"
|
||||
|
||||
### #preview_controller
|
||||
|
||||
Set the controller used for previewing components:
|
||||
|
||||
config.view_component.preview_controller = "MyPreviewController"
|
||||
|
||||
Defaults to `ViewComponentsController`.
|
||||
|
||||
### #preview_path (Deprecated)
|
||||
|
||||
_Use `preview_paths` instead. Will be removed in v3.0.0._
|
||||
|
||||
### #preview_paths
|
||||
|
||||
Set the location of component previews:
|
||||
|
||||
config.view_component.preview_paths << "#{Rails.root}/lib/component_previews"
|
||||
|
||||
### #preview_route
|
||||
|
||||
Set the entry route for component previews:
|
||||
|
||||
config.view_component.preview_route = "/previews"
|
||||
|
||||
Defaults to `/rails/view_components` when `show_previews` is enabled.
|
||||
|
||||
### #render_monkey_patch_enabled
|
||||
|
||||
Set if render monkey patches should be included or not in Rails <6.1:
|
||||
|
||||
config.view_component.render_monkey_patch_enabled = false
|
||||
|
||||
### #show_previews
|
||||
|
||||
Enable or disable component previews:
|
||||
|
||||
config.view_component.show_previews = true
|
||||
|
||||
Defaults to `true` in development.
|
||||
|
||||
### #test_controller
|
||||
|
||||
Set the controller used for testing components:
|
||||
|
||||
config.view_component.test_controller = "MyTestController"
|
||||
|
||||
Defaults to ApplicationController. Can also be configured on a per-test
|
||||
basis using `with_controller_class`.
|
||||
|
|
|
@ -119,7 +119,7 @@ module ViewComponent
|
|||
|
||||
# Called after rendering the component.
|
||||
#
|
||||
# @deprecated Use `before_render` instead. Will be removed in v3.0.0.
|
||||
# @deprecated Use `#before_render` instead. Will be removed in v3.0.0.
|
||||
# @return [void]
|
||||
def before_render_check
|
||||
# noop
|
||||
|
@ -225,17 +225,24 @@ module ViewComponent
|
|||
@__vc_content_evaluated
|
||||
end
|
||||
|
||||
# The controller used for testing components.
|
||||
# Defaults to ApplicationController, but can be configured
|
||||
# on a per-test basis using `with_controller_class`.
|
||||
# This should be set early in the initialization process and should be a string.
|
||||
# Set the controller used for testing components:
|
||||
#
|
||||
# config.view_component.test_controller = "MyTestController"
|
||||
#
|
||||
# Defaults to ApplicationController. Can also be configured on a per-test
|
||||
# basis using `with_controller_class`.
|
||||
#
|
||||
mattr_accessor :test_controller
|
||||
@@test_controller = "ApplicationController"
|
||||
|
||||
# Configure if render monkey patches should be included or not in Rails <6.1.
|
||||
# Set if render monkey patches should be included or not in Rails <6.1:
|
||||
#
|
||||
# config.view_component.render_monkey_patch_enabled = false
|
||||
#
|
||||
mattr_accessor :render_monkey_patch_enabled, instance_writer: false, default: true
|
||||
|
||||
class << self
|
||||
# @private
|
||||
attr_accessor :source_location, :virtual_path
|
||||
|
||||
# EXPERIMENTAL: This API is experimental and may be removed at any time.
|
||||
|
@ -245,6 +252,7 @@ module ViewComponent
|
|||
# strings starting without the "dot", example: `["erb", "haml"]`.
|
||||
#
|
||||
# For example, one might collect sidecar CSS files that need to be compiled.
|
||||
# @private TODO: add documentation
|
||||
def _sidecar_files(extensions)
|
||||
return [] unless source_location
|
||||
|
||||
|
@ -279,16 +287,24 @@ module ViewComponent
|
|||
(sidecar_files - [source_location] + sidecar_directory_files + nested_component_files).uniq
|
||||
end
|
||||
|
||||
# Render a component collection.
|
||||
# Render a component for each element in a collection ([documentation](/guide/collections)):
|
||||
#
|
||||
# render(ProductsComponent.with_collection(@products, foo: :bar))
|
||||
#
|
||||
# @param collection [Enumerable] A list of items to pass the ViewComponent one at a time.
|
||||
# @param args [Arguments] Arguments to pass to the ViewComponent every time.
|
||||
def with_collection(collection, **args)
|
||||
Collection.new(self, collection, **args)
|
||||
end
|
||||
|
||||
# Provide identifier for ActionView template annotations
|
||||
#
|
||||
# @private
|
||||
def short_identifier
|
||||
@short_identifier ||= defined?(Rails.root) ? source_location.sub("#{Rails.root}/", "") : source_location
|
||||
end
|
||||
|
||||
# @private
|
||||
def inherited(child)
|
||||
# Compile so child will inherit compiled `call_*` template methods that
|
||||
# `compile` defines
|
||||
|
@ -311,6 +327,7 @@ module ViewComponent
|
|||
super
|
||||
end
|
||||
|
||||
# @private
|
||||
def compiled?
|
||||
compiler.compiled?
|
||||
end
|
||||
|
@ -319,30 +336,39 @@ module ViewComponent
|
|||
#
|
||||
# Do as much work as possible in this step, as doing so reduces the amount
|
||||
# of work done each time a component is rendered.
|
||||
# @private
|
||||
def compile(raise_errors: false)
|
||||
compiler.compile(raise_errors: raise_errors)
|
||||
end
|
||||
|
||||
# @private
|
||||
def compiler
|
||||
@__vc_compiler ||= Compiler.new(self)
|
||||
end
|
||||
|
||||
# we'll eventually want to update this to support other types
|
||||
# @private
|
||||
def type
|
||||
"text/html"
|
||||
end
|
||||
|
||||
# @private
|
||||
def format
|
||||
:html
|
||||
end
|
||||
|
||||
# @private
|
||||
def identifier
|
||||
source_location
|
||||
end
|
||||
|
||||
# Support overriding collection parameter name
|
||||
def with_collection_parameter(param)
|
||||
@provided_collection_parameter = param
|
||||
# Set the parameter name used when rendering elements of a collection ([documentation](/guide/collections)):
|
||||
#
|
||||
# with_collection_parameter :item
|
||||
#
|
||||
# @param parameter [Symbol] The parameter name used when rendering elements of a collection.
|
||||
def with_collection_parameter(parameter)
|
||||
@provided_collection_parameter = parameter
|
||||
end
|
||||
|
||||
# Ensure the component initializer accepts the
|
||||
|
@ -350,6 +376,7 @@ module ViewComponent
|
|||
# validate that the default parameter name
|
||||
# is accepted, as support for collection
|
||||
# rendering is optional.
|
||||
# @private TODO: add documentation
|
||||
def validate_collection_parameter!(validate_default: false)
|
||||
parameter = validate_default ? collection_parameter : provided_collection_parameter
|
||||
|
||||
|
@ -374,6 +401,7 @@ module ViewComponent
|
|||
# Ensure the component initializer does not define
|
||||
# invalid parameters that could override the framework's
|
||||
# methods.
|
||||
# @private TODO: add documentation
|
||||
def validate_initialization_parameters!
|
||||
return unless initialize_parameter_names.include?(RESERVED_PARAMETER)
|
||||
|
||||
|
@ -384,6 +412,7 @@ module ViewComponent
|
|||
)
|
||||
end
|
||||
|
||||
# @private
|
||||
def collection_parameter
|
||||
if provided_collection_parameter
|
||||
provided_collection_parameter
|
||||
|
@ -392,18 +421,22 @@ module ViewComponent
|
|||
end
|
||||
end
|
||||
|
||||
# @private
|
||||
def collection_counter_parameter
|
||||
"#{collection_parameter}_counter".to_sym
|
||||
end
|
||||
|
||||
# @private
|
||||
def counter_argument_present?
|
||||
initialize_parameter_names.include?(collection_counter_parameter)
|
||||
end
|
||||
|
||||
# @private
|
||||
def collection_iteration_parameter
|
||||
"#{collection_parameter}_iteration".to_sym
|
||||
end
|
||||
|
||||
# @private
|
||||
def iteration_argument_present?
|
||||
initialize_parameter_names.include?(collection_iteration_parameter)
|
||||
end
|
||||
|
|
|
@ -26,7 +26,7 @@ module ViewComponent
|
|||
|
||||
if subclass_instance_methods.include?(:before_render_check)
|
||||
ActiveSupport::Deprecation.warn(
|
||||
"`before_render_check` will be removed in v3.0.0. Use `before_render` instead."
|
||||
"`before_render_check` will be removed in v3.0.0. Use `#before_render` instead."
|
||||
)
|
||||
end
|
||||
|
||||
|
|
|
@ -2,51 +2,49 @@
|
|||
|
||||
require "active_support/concern"
|
||||
|
||||
module ViewComponent # :nodoc:
|
||||
module ViewComponent
|
||||
module Previewable
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
# Set a custom default preview layout through app configuration:
|
||||
# Enable or disable component previews:
|
||||
#
|
||||
# config.view_component.show_previews = true
|
||||
#
|
||||
# Defaults to `true` in development.
|
||||
#
|
||||
mattr_accessor :show_previews, instance_writer: false
|
||||
|
||||
# Set a custom default layout used for preview index and individual previews:
|
||||
#
|
||||
# config.view_component.default_preview_layout = "component_preview"
|
||||
#
|
||||
# This affects preview index pages as well as individual component previews
|
||||
#
|
||||
mattr_accessor :default_preview_layout, instance_writer: false
|
||||
|
||||
# Set the location of component previews through app configuration:
|
||||
# Set the location of component previews:
|
||||
#
|
||||
# config.view_component.preview_paths << "#{Rails.root}/lib/component_previews"
|
||||
#
|
||||
mattr_accessor :preview_paths, instance_writer: false
|
||||
|
||||
# TODO: deprecated, remove in v3.0.0
|
||||
# @deprecated Use `preview_paths` instead. Will be removed in v3.0.0.
|
||||
mattr_accessor :preview_path, instance_writer: false
|
||||
|
||||
# Enable or disable component previews through app configuration:
|
||||
#
|
||||
# config.view_component.show_previews = true
|
||||
#
|
||||
# Defaults to +true+ for development environment
|
||||
#
|
||||
mattr_accessor :show_previews, instance_writer: false
|
||||
|
||||
# Set the entry route for component previews through app configuration:
|
||||
# Set the entry route for component previews:
|
||||
#
|
||||
# config.view_component.preview_route = "/previews"
|
||||
#
|
||||
# Defaults to +/rails/view_components+ when `show_previews' is enabled
|
||||
# Defaults to `/rails/view_components` when `show_previews` is enabled.
|
||||
#
|
||||
mattr_accessor :preview_route, instance_writer: false do
|
||||
"/rails/view_components"
|
||||
end
|
||||
|
||||
# Set the controller to be used for previewing components through app configuration:
|
||||
# Set the controller used for previewing components:
|
||||
#
|
||||
# config.view_component.preview_controller = "MyPreviewController"
|
||||
#
|
||||
# Defaults to the provided +ViewComponentsController+
|
||||
# Defaults to `ViewComponentsController`.
|
||||
#
|
||||
mattr_accessor :preview_controller, instance_writer: false do
|
||||
"ViewComponentsController"
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module YARD
|
||||
# YARD Handler to parse `mattr_accessor` calls.
|
||||
class MattrAccessorHandler < YARD::Handlers::Ruby::Base
|
||||
handles method_call(:mattr_accessor)
|
||||
namespace_only
|
||||
|
||||
process do
|
||||
name = statement.parameters.first.jump(:tstring_content, :ident).source
|
||||
object = YARD::CodeObjects::MethodObject.new(namespace, name)
|
||||
register(object)
|
||||
parse_block(statement.last, owner: object)
|
||||
|
||||
object.dynamic = true
|
||||
object[:mattr_accessor] = true
|
||||
end
|
||||
end
|
||||
end
|
|
@ -43,4 +43,5 @@ Gem::Specification.new do |spec|
|
|||
spec.add_development_dependency "simplecov-console", "~> 0.7.2"
|
||||
spec.add_development_dependency "pry", "~> 0.13"
|
||||
spec.add_development_dependency "yard", "~> 0.9.25"
|
||||
spec.add_development_dependency "yard-activesupport-concern"
|
||||
end
|
||||
|
|
Загрузка…
Ссылка в новой задаче