Module: DocsKit::Registry
- Defined in:
- lib/docs_kit/registry.rb
Overview
A mixin for an in-memory docs registry (guides, demos, component references).
Two authoring styles, one shared lookup/grouping API:
-
The one-line
pageDSL (v2) — the default a site should reach for. slug and view derive from the title (both overridable); instances get default readers + view_class + href for free; the sidebar nav derives from the registry with zero site code:class Doc extend DocsKit::Registry path_prefix "/docs" # href = "#{path_prefix}/#{slug}" view_namespace "Views::Docs::Pages" # view_class resolves under this page "Installation", group: "Guide" # slug "installation", view "Installation" page "Getting started", group: "Guide", icon: "rocket" # slug "getting-started", view "GettingStarted" page "OAuth", group: "Guide", slug: "auth", view: "OauthGuide" # every derivation overridable end -
The low-level hash
entriesAPI — for a registry with a bespoke schema (custom fields, a non-default view namespace). The site writes its own initialize/readers/view_class:class Demo extend DocsKit::Registry entries [{ slug: "counter", title: "Counter", group: "Examples", view: "Counter" }] attr_reader :slug, :title, :group, :view_name def initialize(entry) = (@slug, @title, @group, @view_name = entry.values_at(:slug, :title, :group, :view)) def view_class = "Views::Docs::Pages::#{view_name}".safe_constantize end
Doc.all # => [entry instances] Doc.from_slug("installation") # => instance | nil Doc.grouped # => { "Guide" => [instances] } Doc.nav_items # => { "Guide" => [NavItem] } (authored pages only)
A registry uses ONE style; mixing page and entries raises Registry::Error.
Defined Under Namespace
Instance Method Summary collapse
-
#all ⇒ Object
All registry instances (built fresh each call — instances are cheap and a site may resolve view classes that change under code reload in development).
-
#entries(list = nil) ⇒ Object
Declares the frozen registry data directly (the low-level hash API).
-
#from_slug(slug) ⇒ Object
The instance whose slug matches, or nil.
-
#group_by_attribute(attr = nil) ⇒ Object
The attribute used by #grouped (default :group).
-
#grouped ⇒ Object
{ group_value => [instances] }, preserving registry order within a group.
-
#nav_items ⇒ Object
{ group => [NavItem] } for authored pages only (a resolvable view_class), so the sidebar never links a page that isn't written yet.
-
#page(title, group:, slug: nil, view: nil, icon: nil) ⇒ Object
Declares one page (the v2 DSL).
-
#path_prefix(value = nil) ⇒ Object
href = "##path_prefix/#slug".
-
#view_namespace(value = nil) ⇒ Object
The namespace a page's view_class resolves under (v2 pages only), e.g.
Instance Method Details
#all ⇒ Object
All registry instances (built fresh each call — instances are cheap and a site may resolve view classes that change under code reload in development). v2 pages are wrapped in the default Entry; hash entries in the site's class.
99 100 101 102 103 104 105 |
# File 'lib/docs_kit/registry.rb', line 99 def all if defined?(@pages) && @pages @pages.map { |attrs| Entry.new(attrs, path_prefix, view_namespace) } else (entries || []).map { |entry| new(entry) } end end |
#entries(list = nil) ⇒ Object
Declares the frozen registry data directly (the low-level hash API). Each entry is a Hash; the site supplies its own instance class behavior.
53 54 55 56 57 58 59 |
# File 'lib/docs_kit/registry.rb', line 53 def entries(list = nil) return @entries if list.nil? raise Error, "cannot mix `page` and `entries` in one registry" if @pages&.any? @entries = list.map(&:freeze).freeze end |
#from_slug(slug) ⇒ Object
The instance whose slug matches, or nil.
108 109 110 |
# File 'lib/docs_kit/registry.rb', line 108 def from_slug(slug) all.find { |item| item.slug.to_s == slug.to_s } end |
#group_by_attribute(attr = nil) ⇒ Object
The attribute used by #grouped (default :group).
91 92 93 94 |
# File 'lib/docs_kit/registry.rb', line 91 def group_by_attribute(attr = nil) @group_by_attribute = attr if attr @group_by_attribute || :group end |
#grouped ⇒ Object
{ group_value => [instances] }, preserving registry order within a group.
113 114 115 |
# File 'lib/docs_kit/registry.rb', line 113 def grouped all.group_by { |item| item.public_send(group_by_attribute) } end |
#nav_items ⇒ Object
{ group => [NavItem] } for authored pages only (a resolvable view_class), so the sidebar never links a page that isn't written yet. This is the transform every site used to hand-write in its nav lambda.
120 121 122 123 124 125 126 |
# File 'lib/docs_kit/registry.rb', line 120 def nav_items all.select { |item| item.respond_to?(:view_class) && item.view_class } .group_by { |item| item.public_send(group_by_attribute) } .transform_values do |items| items.map { |item| DocsKit::NavItem.new(href: item.href, label: item.title, icon: item.icon) } end end |
#page(title, group:, slug: nil, view: nil, icon: nil) ⇒ Object
Declares one page (the v2 DSL). slug/view derive from the title unless given. Appends to the registry in declaration order (== sidebar order).
page "Getting started", group: "Guide", icon: "rocket", slug: "start", view: "Start"
65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/docs_kit/registry.rb', line 65 def page(title, group:, slug: nil, view: nil, icon: nil) raise Error, "cannot mix `page` and `entries` in one registry" if defined?(@entries) && @entries (@pages ||= []) << { title: title, group: group, slug: slug || title.parameterize, view: view || title.parameterize(separator: "_").camelize, icon: icon }.freeze end |
#path_prefix(value = nil) ⇒ Object
href = "##path_prefix/#slug". Defaults to "/docs".
78 79 80 81 |
# File 'lib/docs_kit/registry.rb', line 78 def path_prefix(value = nil) @path_prefix = value if value @path_prefix || "/docs" end |
#view_namespace(value = nil) ⇒ Object
The namespace a page's view_class resolves under (v2 pages only), e.g. "Views::Docs::Pages". Required to resolve views via the default Entry.
85 86 87 88 |
# File 'lib/docs_kit/registry.rb', line 85 def view_namespace(value = nil) @view_namespace = value if value @view_namespace end |