chiridion 0.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +25 -0
- data/LICENSE.txt +21 -0
- data/README.md +201 -0
- data/lib/chiridion/config.rb +128 -0
- data/lib/chiridion/engine/class_linker.rb +204 -0
- data/lib/chiridion/engine/document_model.rb +299 -0
- data/lib/chiridion/engine/drift_checker.rb +146 -0
- data/lib/chiridion/engine/extractor.rb +311 -0
- data/lib/chiridion/engine/file_renderer.rb +717 -0
- data/lib/chiridion/engine/file_writer.rb +160 -0
- data/lib/chiridion/engine/frontmatter_builder.rb +248 -0
- data/lib/chiridion/engine/generated_rbs_loader.rb +344 -0
- data/lib/chiridion/engine/github_linker.rb +87 -0
- data/lib/chiridion/engine/inline_rbs_loader.rb +207 -0
- data/lib/chiridion/engine/post_processor.rb +86 -0
- data/lib/chiridion/engine/rbs_loader.rb +150 -0
- data/lib/chiridion/engine/rbs_type_alias_loader.rb +116 -0
- data/lib/chiridion/engine/renderer.rb +598 -0
- data/lib/chiridion/engine/semantic_extractor.rb +740 -0
- data/lib/chiridion/engine/semantic_renderer.rb +334 -0
- data/lib/chiridion/engine/spec_example_loader.rb +84 -0
- data/lib/chiridion/engine/template_renderer.rb +275 -0
- data/lib/chiridion/engine/type_merger.rb +126 -0
- data/lib/chiridion/engine/writer.rb +134 -0
- data/lib/chiridion/engine.rb +359 -0
- data/lib/chiridion/semantic_engine.rb +186 -0
- data/lib/chiridion/version.rb +5 -0
- data/lib/chiridion.rb +106 -0
- data/templates/constants.liquid +27 -0
- data/templates/document.liquid +48 -0
- data/templates/file.liquid +108 -0
- data/templates/index.liquid +21 -0
- data/templates/method.liquid +43 -0
- data/templates/methods.liquid +11 -0
- data/templates/type_aliases.liquid +26 -0
- data/templates/types.liquid +11 -0
- metadata +146 -0
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "fileutils"
|
|
4
|
+
require "logger"
|
|
5
|
+
|
|
6
|
+
module Chiridion
|
|
7
|
+
# Semantic documentation engine - outputs structured JSON data.
|
|
8
|
+
#
|
|
9
|
+
# This is an alternative to the regular Engine that focuses on semantic
|
|
10
|
+
# extraction and outputs machine-readable JSON alongside markdown. It's
|
|
11
|
+
# useful for:
|
|
12
|
+
#
|
|
13
|
+
# - Verifying what data is being captured
|
|
14
|
+
# - Debugging the extraction pipeline
|
|
15
|
+
# - Generating LLM-friendly documentation
|
|
16
|
+
# - Separating extraction from presentation
|
|
17
|
+
#
|
|
18
|
+
# Usage:
|
|
19
|
+
# engine = Chiridion::SemanticEngine.new(
|
|
20
|
+
# paths: ['lib/myproject'],
|
|
21
|
+
# output: 'docs/sys',
|
|
22
|
+
# namespace_filter: 'MyProject::'
|
|
23
|
+
# )
|
|
24
|
+
# engine.refresh
|
|
25
|
+
#
|
|
26
|
+
class SemanticEngine
|
|
27
|
+
attr_reader :paths, :output
|
|
28
|
+
|
|
29
|
+
def initialize(
|
|
30
|
+
paths:,
|
|
31
|
+
output:,
|
|
32
|
+
namespace_filter: nil,
|
|
33
|
+
namespace_strip: nil,
|
|
34
|
+
include_specs: false,
|
|
35
|
+
verbose: false,
|
|
36
|
+
logger: nil,
|
|
37
|
+
root: Dir.pwd,
|
|
38
|
+
rbs_path: "sig",
|
|
39
|
+
spec_path: "test",
|
|
40
|
+
project_title: "API Documentation",
|
|
41
|
+
project_description: nil
|
|
42
|
+
)
|
|
43
|
+
@paths = Array(paths)
|
|
44
|
+
@output = output
|
|
45
|
+
@namespace_filter = namespace_filter
|
|
46
|
+
@namespace_strip = namespace_strip || namespace_filter
|
|
47
|
+
@include_specs = include_specs
|
|
48
|
+
@verbose = verbose
|
|
49
|
+
@logger = logger || DefaultLogger.new
|
|
50
|
+
@root = root
|
|
51
|
+
@rbs_path = rbs_path
|
|
52
|
+
@spec_path = spec_path
|
|
53
|
+
@project_title = project_title
|
|
54
|
+
@project_description = project_description
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def refresh
|
|
58
|
+
require "yard"
|
|
59
|
+
register_rbs_tag
|
|
60
|
+
|
|
61
|
+
@logger.info "Semantic extraction from #{paths_description}..."
|
|
62
|
+
|
|
63
|
+
# Load sources
|
|
64
|
+
load_sources
|
|
65
|
+
|
|
66
|
+
# Extract using SemanticExtractor
|
|
67
|
+
project_doc = extract_documentation
|
|
68
|
+
|
|
69
|
+
# Render to JSON+markdown
|
|
70
|
+
files = render_documentation(project_doc)
|
|
71
|
+
|
|
72
|
+
# Write files
|
|
73
|
+
write_files(files)
|
|
74
|
+
|
|
75
|
+
@logger.info "Semantic docs written to #{@output}/ (#{files.size} files)"
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
private
|
|
79
|
+
|
|
80
|
+
def paths_description = @paths.size == 1 ? @paths.first : "#{@paths.size} paths"
|
|
81
|
+
|
|
82
|
+
def register_rbs_tag
|
|
83
|
+
return if YARD::Tags::Library.labels.key?(:rbs)
|
|
84
|
+
|
|
85
|
+
YARD::Tags::Library.define_tag("RBS type annotation", :rbs, :with_types_and_name)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def load_sources
|
|
89
|
+
YARD::Logger.instance.level = @verbose ? ::Logger::WARN : ::Logger::ERROR
|
|
90
|
+
|
|
91
|
+
@source_files = @paths.flat_map { |p| resolve_ruby_files(p) }.map { |f| File.expand_path(f) }
|
|
92
|
+
|
|
93
|
+
YARD::Registry.clear
|
|
94
|
+
YARD.parse(@source_files)
|
|
95
|
+
|
|
96
|
+
# Load from generated RBS (authoritative types)
|
|
97
|
+
rbs_generated_dir = find_rbs_generated_dir
|
|
98
|
+
if rbs_generated_dir
|
|
99
|
+
@rbs_data = Engine::GeneratedRbsLoader.new(verbose: @verbose, logger: @logger).load(rbs_generated_dir)
|
|
100
|
+
@logger.info "Loaded types from #{rbs_generated_dir}" if @verbose
|
|
101
|
+
else
|
|
102
|
+
@rbs_data = Engine::GeneratedRbsLoader::Result.new(
|
|
103
|
+
signatures: {}, ivars: {}, attrs: {}, type_aliases: {}, overloads: {}
|
|
104
|
+
)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Load spec examples if enabled
|
|
108
|
+
@spec_examples = @include_specs ? Engine::SpecExampleLoader.new(@spec_path, @verbose, @logger).load : {}
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def find_rbs_generated_dir
|
|
112
|
+
generated_dir = File.join(@root, @rbs_path, "generated")
|
|
113
|
+
return generated_dir if Dir.exist?(generated_dir)
|
|
114
|
+
|
|
115
|
+
sig_dir = File.join(@root, @rbs_path)
|
|
116
|
+
return sig_dir if Dir.exist?(sig_dir)
|
|
117
|
+
|
|
118
|
+
nil
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def resolve_ruby_files(path)
|
|
122
|
+
if File.directory?(path)
|
|
123
|
+
Dir.glob("#{path}/**/*.rb")
|
|
124
|
+
elsif File.file?(path) && path.end_with?(".rb")
|
|
125
|
+
[path]
|
|
126
|
+
else
|
|
127
|
+
@logger.warn "Skipping invalid path: #{path}"
|
|
128
|
+
[]
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def extract_documentation
|
|
133
|
+
extractor = Engine::SemanticExtractor.new(
|
|
134
|
+
rbs_types: @rbs_data.signatures,
|
|
135
|
+
rbs_attr_types: @rbs_data.attrs,
|
|
136
|
+
rbs_ivar_types: @rbs_data.ivars,
|
|
137
|
+
type_aliases: @rbs_data.type_aliases,
|
|
138
|
+
spec_examples: @spec_examples,
|
|
139
|
+
namespace_filter: @namespace_filter,
|
|
140
|
+
logger: @logger
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
extractor.extract(
|
|
144
|
+
YARD::Registry,
|
|
145
|
+
title: @project_title,
|
|
146
|
+
description: @project_description
|
|
147
|
+
)
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def render_documentation(project_doc)
|
|
151
|
+
renderer = Engine::SemanticRenderer.new(
|
|
152
|
+
namespace_strip: @namespace_strip,
|
|
153
|
+
project_title: @project_title
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
renderer.render(project_doc)
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def write_files(files)
|
|
160
|
+
FileUtils.mkdir_p(@output)
|
|
161
|
+
|
|
162
|
+
files.each do |filename, content|
|
|
163
|
+
filepath = File.join(@output, filename)
|
|
164
|
+
dir = File.dirname(filepath)
|
|
165
|
+
FileUtils.mkdir_p(dir) unless File.directory?(dir)
|
|
166
|
+
|
|
167
|
+
# Only write if content changed
|
|
168
|
+
if File.exist?(filepath)
|
|
169
|
+
existing = File.read(filepath)
|
|
170
|
+
next if existing == content
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
File.write(filepath, content)
|
|
174
|
+
@logger.info " Wrote #{filename}" if @verbose
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
# Load required components
|
|
181
|
+
require_relative "engine/document_model"
|
|
182
|
+
require_relative "engine/generated_rbs_loader"
|
|
183
|
+
require_relative "engine/semantic_extractor"
|
|
184
|
+
require_relative "engine/semantic_renderer"
|
|
185
|
+
require_relative "engine/type_merger"
|
|
186
|
+
require_relative "engine/spec_example_loader"
|
data/lib/chiridion.rb
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "chiridion/version"
|
|
4
|
+
require_relative "chiridion/config"
|
|
5
|
+
require_relative "chiridion/engine"
|
|
6
|
+
|
|
7
|
+
# Chiridion: Agent-oriented documentation generator for Ruby projects.
|
|
8
|
+
#
|
|
9
|
+
# Chiridion ("handbook" in Greek, from the same root as Enchiridion) generates
|
|
10
|
+
# documentation optimized for AI agents and LLMs working with Ruby codebases.
|
|
11
|
+
# It extracts documentation from YARD comments, merges RBS type signatures,
|
|
12
|
+
# and produces structured markdown suitable for context injection.
|
|
13
|
+
#
|
|
14
|
+
# ## Key Features
|
|
15
|
+
#
|
|
16
|
+
# - **YARD Integration**: Extracts docstrings, @param, @return, @example tags
|
|
17
|
+
# - **RBS Authority**: RBS type signatures are authoritative over YARD types
|
|
18
|
+
# - **Spec Examples**: Extracts usage examples from RSpec files
|
|
19
|
+
# - **Wikilinks**: Obsidian-compatible [[Class::Name]] cross-references
|
|
20
|
+
# - **Drift Detection**: CI mode to ensure docs stay in sync with code
|
|
21
|
+
#
|
|
22
|
+
# ## Design Philosophy
|
|
23
|
+
#
|
|
24
|
+
# Traditional documentation is written for human developers reading in browsers.
|
|
25
|
+
# Agent-oriented documentation is optimized for LLMs processing in context windows:
|
|
26
|
+
#
|
|
27
|
+
# - Structured frontmatter with navigation metadata
|
|
28
|
+
# - Explicit type information (not just prose descriptions)
|
|
29
|
+
# - Cross-reference links that can be followed programmatically
|
|
30
|
+
# - Compact but complete method signatures
|
|
31
|
+
#
|
|
32
|
+
# @example Basic usage
|
|
33
|
+
# engine = Chiridion::Engine.new(
|
|
34
|
+
# paths: ['lib/myproject'],
|
|
35
|
+
# output: 'docs/sys',
|
|
36
|
+
# namespace_filter: 'MyProject::'
|
|
37
|
+
# )
|
|
38
|
+
# engine.refresh
|
|
39
|
+
#
|
|
40
|
+
# @example Configuration block
|
|
41
|
+
# Chiridion.configure do |config|
|
|
42
|
+
# config.output = 'docs/sys'
|
|
43
|
+
# config.namespace_filter = 'MyProject::'
|
|
44
|
+
# config.github_repo = 'user/repo'
|
|
45
|
+
# config.include_specs = true
|
|
46
|
+
# end
|
|
47
|
+
# Chiridion.refresh(['lib/myproject'])
|
|
48
|
+
#
|
|
49
|
+
module Chiridion
|
|
50
|
+
class Error < StandardError; end
|
|
51
|
+
|
|
52
|
+
class << self
|
|
53
|
+
# @return [Config] Global configuration instance
|
|
54
|
+
def config = @config ||= Config.new
|
|
55
|
+
|
|
56
|
+
# Configure Chiridion with a block.
|
|
57
|
+
#
|
|
58
|
+
# @yield [Config] Configuration object
|
|
59
|
+
# @return [Config] Configured instance
|
|
60
|
+
def configure
|
|
61
|
+
yield config
|
|
62
|
+
config
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Reset configuration to defaults (useful for testing).
|
|
66
|
+
def reset_config! = @config = Config.new
|
|
67
|
+
|
|
68
|
+
# Convenience method to run documentation refresh.
|
|
69
|
+
#
|
|
70
|
+
# @param paths [Array<String>] Source paths to document
|
|
71
|
+
# @param output [String, nil] Override output directory
|
|
72
|
+
# @return [void]
|
|
73
|
+
def refresh(paths = nil, output: nil)
|
|
74
|
+
engine = Engine.new(
|
|
75
|
+
paths: paths || [config.source_path],
|
|
76
|
+
output: output || config.output,
|
|
77
|
+
namespace_filter: config.namespace_filter,
|
|
78
|
+
include_specs: config.include_specs,
|
|
79
|
+
verbose: config.verbose,
|
|
80
|
+
logger: config.logger,
|
|
81
|
+
inline_source_threshold: config.inline_source_threshold,
|
|
82
|
+
output_mode: config.output_mode
|
|
83
|
+
)
|
|
84
|
+
engine.refresh
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Convenience method to check for documentation drift.
|
|
88
|
+
#
|
|
89
|
+
# @param paths [Array<String>] Source paths to check
|
|
90
|
+
# @return [void]
|
|
91
|
+
# @raise [SystemExit] Exits with code 1 if drift detected
|
|
92
|
+
def check(paths = nil)
|
|
93
|
+
engine = Engine.new(
|
|
94
|
+
paths: paths || [config.source_path],
|
|
95
|
+
output: config.output,
|
|
96
|
+
namespace_filter: config.namespace_filter,
|
|
97
|
+
include_specs: config.include_specs,
|
|
98
|
+
verbose: config.verbose,
|
|
99
|
+
logger: config.logger,
|
|
100
|
+
inline_source_threshold: config.inline_source_threshold,
|
|
101
|
+
output_mode: config.output_mode
|
|
102
|
+
)
|
|
103
|
+
engine.check
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{% comment %}
|
|
2
|
+
Constants section template.
|
|
3
|
+
Variables:
|
|
4
|
+
- constants: Array of {name:, value:, docstring:, is_complex:}
|
|
5
|
+
- complex_constants: Array of complex constants for separate rendering
|
|
6
|
+
{% endcomment %}
|
|
7
|
+
## Constants
|
|
8
|
+
{%- assign has_simple = false %}{% for c in constants %}{% unless c.is_complex %}{% assign has_simple = true %}{% endunless %}{% endfor %}
|
|
9
|
+
{%- if has_simple %}
|
|
10
|
+
|
|
11
|
+
| Constant | Value | Description |
|
|
12
|
+
|----------|-------|-------------|
|
|
13
|
+
{% for c in constants %}{%- unless c.is_complex -%}
|
|
14
|
+
| `{{ c.name }}` | `{{ c.value | escape_pipes }}` | {{ c.docstring | strip_rbs_blocks | strip_newlines }} |
|
|
15
|
+
{% endunless -%}{% endfor -%}
|
|
16
|
+
{%- endif -%}
|
|
17
|
+
{%- for c in complex_constants %}
|
|
18
|
+
|
|
19
|
+
### {{ c.name }}
|
|
20
|
+
{% assign clean_doc = c.docstring | strip_rbs_blocks | normalize_headers: 4 -%}
|
|
21
|
+
{%- if clean_doc != blank %}
|
|
22
|
+
{{ clean_doc }}
|
|
23
|
+
{% endif -%}
|
|
24
|
+
```ruby
|
|
25
|
+
{{ c.name }} = {{ c.value }}
|
|
26
|
+
```
|
|
27
|
+
{%- endfor -%}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{%- comment -%}Class/module document template.{%- endcomment -%}
|
|
2
|
+
# {{ title }}
|
|
3
|
+
|
|
4
|
+
{{ docstring | normalize_headers: 3 }}
|
|
5
|
+
{%- if mixins %}
|
|
6
|
+
|
|
7
|
+
{{ mixins }}
|
|
8
|
+
{%- endif -%}
|
|
9
|
+
{%- if examples.size > 0 %}
|
|
10
|
+
|
|
11
|
+
## Example
|
|
12
|
+
{%- for ex in examples %}
|
|
13
|
+
{%- unless ex.name == blank or ex.name == '' %}
|
|
14
|
+
|
|
15
|
+
**{{ ex.name }}**
|
|
16
|
+
{%- endunless %}
|
|
17
|
+
|
|
18
|
+
```ruby
|
|
19
|
+
{{ ex.text }}
|
|
20
|
+
```
|
|
21
|
+
{%- unless forloop.last %}
|
|
22
|
+
{% endunless -%}
|
|
23
|
+
{%- endfor -%}
|
|
24
|
+
{%- endif -%}
|
|
25
|
+
{%- if spec_examples %}
|
|
26
|
+
|
|
27
|
+
{{ spec_examples }}
|
|
28
|
+
{%- endif -%}
|
|
29
|
+
{%- if see_also %}
|
|
30
|
+
|
|
31
|
+
{{ see_also }}
|
|
32
|
+
{%- endif -%}
|
|
33
|
+
{%- if constants_section != blank %}
|
|
34
|
+
|
|
35
|
+
{{ constants_section }}
|
|
36
|
+
{%- endif -%}
|
|
37
|
+
{%- if types_section != blank %}
|
|
38
|
+
|
|
39
|
+
{{ types_section }}
|
|
40
|
+
{%- endif -%}
|
|
41
|
+
{%- if attributes_section != blank %}
|
|
42
|
+
|
|
43
|
+
{{ attributes_section }}
|
|
44
|
+
{%- endif -%}
|
|
45
|
+
{%- if methods_section != blank %}
|
|
46
|
+
|
|
47
|
+
{{ methods_section }}
|
|
48
|
+
{%- endif -%}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
{% comment %}
|
|
2
|
+
Per-file documentation template.
|
|
3
|
+
|
|
4
|
+
Variables:
|
|
5
|
+
- path: Source file path (relative)
|
|
6
|
+
- filename: Just the filename
|
|
7
|
+
- line_count: Total lines in source
|
|
8
|
+
- namespaces: Array of namespace objects, each with:
|
|
9
|
+
- name: Short name
|
|
10
|
+
- path: Full path (e.g., "Archema::Query")
|
|
11
|
+
- type: "class" or "module"
|
|
12
|
+
- superclass: Parent class path (if class)
|
|
13
|
+
- docstring: Main documentation
|
|
14
|
+
- mixins: Pre-rendered mixin line
|
|
15
|
+
- examples: Array of {name:, code:}
|
|
16
|
+
- notes: Array of note strings
|
|
17
|
+
- type_aliases: Array of {name:, definition:, description:}
|
|
18
|
+
- types_section: Pre-rendered referenced types (## Types Used)
|
|
19
|
+
- constants_section: Pre-rendered constants
|
|
20
|
+
- summary_section: Pre-rendered attributes + method signatures
|
|
21
|
+
- methods_section: Pre-rendered methods
|
|
22
|
+
- private_summary: Pre-rendered private methods list
|
|
23
|
+
{% endcomment %}
|
|
24
|
+
{% for ns in namespaces %}
|
|
25
|
+
{%- unless forloop.first %}
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
{% endunless %}
|
|
29
|
+
# {{ ns.type | capitalize }}: {{ ns.path }}
|
|
30
|
+
{%- if ns.superclass %}
|
|
31
|
+
|
|
32
|
+
**Extends:** {{ ns.superclass }}
|
|
33
|
+
{%- endif %}
|
|
34
|
+
{%- if ns.mixins %}
|
|
35
|
+
|
|
36
|
+
{{ ns.mixins }}
|
|
37
|
+
{%- endif %}
|
|
38
|
+
{%- if ns.abstract %}
|
|
39
|
+
|
|
40
|
+
> **Abstract:** This {{ ns.type }} must be subclassed.
|
|
41
|
+
{%- endif %}
|
|
42
|
+
{%- if ns.deprecated %}
|
|
43
|
+
|
|
44
|
+
> **Deprecated:** {{ ns.deprecated }}
|
|
45
|
+
{%- endif %}
|
|
46
|
+
{%- if ns.docstring != blank %}
|
|
47
|
+
|
|
48
|
+
{{ ns.docstring | normalize_headers: 3 }}
|
|
49
|
+
{%- endif %}
|
|
50
|
+
{%- if ns.notes.size > 0 %}
|
|
51
|
+
{% for note in ns.notes %}
|
|
52
|
+
|
|
53
|
+
> **Note:** {{ note }}
|
|
54
|
+
{%- endfor %}
|
|
55
|
+
{%- endif %}
|
|
56
|
+
{%- if ns.examples.size > 0 %}
|
|
57
|
+
|
|
58
|
+
### Example
|
|
59
|
+
{%- for ex in ns.examples %}
|
|
60
|
+
{%- if ex.name != blank %}
|
|
61
|
+
|
|
62
|
+
**{{ ex.name }}**
|
|
63
|
+
{%- endif %}
|
|
64
|
+
|
|
65
|
+
```ruby
|
|
66
|
+
{{ ex.code }}
|
|
67
|
+
```
|
|
68
|
+
{%- endfor %}
|
|
69
|
+
{%- endif %}
|
|
70
|
+
{%- if ns.see_also.size > 0 %}
|
|
71
|
+
|
|
72
|
+
**See also:** {% for see in ns.see_also %}{{ see.target }}{% if see.text %} ({{ see.text }}){% endif %}{% unless forloop.last %}, {% endunless %}{% endfor %}
|
|
73
|
+
{%- endif %}
|
|
74
|
+
{%- if ns.type_aliases.size > 0 %}
|
|
75
|
+
|
|
76
|
+
## Types
|
|
77
|
+
{%- for ta in ns.type_aliases %}
|
|
78
|
+
|
|
79
|
+
### {{ ta.name }}
|
|
80
|
+
|
|
81
|
+
: `{{ ta.definition }}`
|
|
82
|
+
{%- if ta.description != blank %}
|
|
83
|
+
|
|
84
|
+
{{ ta.description }}
|
|
85
|
+
{%- endif %}
|
|
86
|
+
{%- endfor %}
|
|
87
|
+
{%- endif %}
|
|
88
|
+
{%- if ns.types_section != blank %}
|
|
89
|
+
|
|
90
|
+
{{ ns.types_section }}
|
|
91
|
+
{%- endif %}
|
|
92
|
+
{%- if ns.constants_section != blank %}
|
|
93
|
+
|
|
94
|
+
{{ ns.constants_section }}
|
|
95
|
+
{%- endif %}
|
|
96
|
+
{%- if ns.summary_section != blank %}
|
|
97
|
+
|
|
98
|
+
{{ ns.summary_section }}
|
|
99
|
+
{%- endif %}
|
|
100
|
+
{%- if ns.methods_section != blank %}
|
|
101
|
+
|
|
102
|
+
{{ ns.methods_section }}
|
|
103
|
+
{%- endif %}
|
|
104
|
+
{%- if ns.private_summary != blank %}
|
|
105
|
+
|
|
106
|
+
{{ ns.private_summary }}
|
|
107
|
+
{%- endif %}
|
|
108
|
+
{% endfor -%}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{% comment %}
|
|
2
|
+
Index page template for documentation.
|
|
3
|
+
Variables:
|
|
4
|
+
- title: Project title
|
|
5
|
+
- description: Index page description
|
|
6
|
+
- classes: Array of {path:, link_path:}
|
|
7
|
+
- modules: Array of {path:, link_path:}
|
|
8
|
+
{% endcomment %}
|
|
9
|
+
# {{ title }}
|
|
10
|
+
|
|
11
|
+
> {{ description }}
|
|
12
|
+
|
|
13
|
+
## Classes
|
|
14
|
+
|
|
15
|
+
{% for klass in classes %}- [[{{ klass.link_path }}|{{ klass.path }}]]
|
|
16
|
+
{% endfor %}
|
|
17
|
+
|
|
18
|
+
## Modules
|
|
19
|
+
|
|
20
|
+
{% for mod in modules %}- [[{{ mod.link_path }}|{{ mod.path }}]]
|
|
21
|
+
{% endfor %}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{%- comment -%}Method documentation template.{%- endcomment -%}
|
|
2
|
+
### {{ display_name }}{% if has_params %}(...){% endif %}
|
|
3
|
+
{%- if docstring %}
|
|
4
|
+
{{ docstring | normalize_headers: 4 }}
|
|
5
|
+
{%- endif -%}
|
|
6
|
+
{%- if params.size > 0 or return_line %}
|
|
7
|
+
|
|
8
|
+
{% for param in params -%}
|
|
9
|
+
{{ param }}
|
|
10
|
+
{% endfor -%}
|
|
11
|
+
{%- if return_line -%}
|
|
12
|
+
{{ return_line }}
|
|
13
|
+
{% endif %}
|
|
14
|
+
{%- endif -%}
|
|
15
|
+
{%- for ex in examples %}
|
|
16
|
+
|
|
17
|
+
**{% if ex.name %}Example: {{ ex.name }}{% else %}Example{% endif %}:**
|
|
18
|
+
|
|
19
|
+
```ruby
|
|
20
|
+
{{ ex.text }}
|
|
21
|
+
```
|
|
22
|
+
{%- endfor -%}
|
|
23
|
+
{%- if behaviors.size > 0 %}
|
|
24
|
+
|
|
25
|
+
**Tested behaviors:**
|
|
26
|
+
{%- for b in behaviors %}
|
|
27
|
+
- {{ b }}
|
|
28
|
+
{%- endfor -%}
|
|
29
|
+
{%- endif -%}
|
|
30
|
+
{%- for ex in spec_examples %}
|
|
31
|
+
|
|
32
|
+
**From specs ({{ ex.name }}):**
|
|
33
|
+
|
|
34
|
+
```ruby
|
|
35
|
+
{{ ex.code }}
|
|
36
|
+
```
|
|
37
|
+
{%- endfor -%}
|
|
38
|
+
{%- if inline_source %}
|
|
39
|
+
|
|
40
|
+
```ruby
|
|
41
|
+
{{ inline_source }}
|
|
42
|
+
```
|
|
43
|
+
{%- endif -%}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{% comment %}
|
|
2
|
+
Type aliases reference page template.
|
|
3
|
+
Variables:
|
|
4
|
+
- title: Page title
|
|
5
|
+
- description: Page description
|
|
6
|
+
- namespaces: Array of { name:, types: [...] } where types have name, definition, description
|
|
7
|
+
{% endcomment %}
|
|
8
|
+
# {{ title }}
|
|
9
|
+
|
|
10
|
+
> {{ description }}
|
|
11
|
+
|
|
12
|
+
{% for ns in namespaces %}
|
|
13
|
+
## {{ ns.name }}
|
|
14
|
+
|
|
15
|
+
{% for type in ns.types %}
|
|
16
|
+
### `{{ type.name }}`
|
|
17
|
+
|
|
18
|
+
{% if type.description %}{{ type.description }}
|
|
19
|
+
|
|
20
|
+
{% endif %}
|
|
21
|
+
```rbs
|
|
22
|
+
type {{ type.name }} = {{ type.definition }}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
{% endfor %}
|
|
26
|
+
{% endfor %}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{%- comment -%}Types section template - displays type aliases used by a class/module.{%- endcomment -%}
|
|
2
|
+
## Types
|
|
3
|
+
|
|
4
|
+
{%- for type in types %}
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
### {{ type.name }}
|
|
8
|
+
{% if type.description %}(*{{ type.description }}*)
|
|
9
|
+
{% endif %}
|
|
10
|
+
`{{ type.definition }}`
|
|
11
|
+
{%- endfor -%}
|