zard-doc 0.0.1
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/LICENSE +5 -0
- data/README.md +46 -0
- data/exe/zard-doc +6 -0
- data/lib/zard/doc/cli.rb +152 -0
- data/lib/zard/doc/renderer.rb +186 -0
- data/lib/zard/doc/version.rb +7 -0
- data/lib/zard/doc.rb +15 -0
- metadata +66 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: d4a7ff58279b52ea8ca3e15ffdf25f54214d20c5ececaeb641282e85050d3d5a
|
|
4
|
+
data.tar.gz: 9ede39071e88157e47387cf29ae4b4c04a8af656c396e26c783824b671c52ce4
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: ed9d9d91a23b003910e34db882cfec727154822a60bf66c92e2f996bd9c2c94d0796c15e9603be569846b43985585eae8f74a24a722ca0fe3e60b7d985217ebe
|
|
7
|
+
data.tar.gz: 9d9d1e2a24d28de2d6080bc397734ab2f1de2d4623dc9cc4c3e70335e3801c0e8ee6d3aeff7b48e36a1234fd3d950407eb660d7452e9ab0c0f31c2a1ec657d45
|
data/LICENSE
ADDED
data/README.md
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# zard-doc
|
|
2
|
+
|
|
3
|
+
`zard-doc` renders API documentation from the versioned model produced by `zard`.
|
|
4
|
+
|
|
5
|
+
See the [ZARD usage guide](https://github.com/rigortype/zard/blob/master/docs/usage.md) for installation, canonical tag syntax, model access, limitations, and exit codes. The `0.0.1` candidate is not yet published on RubyGems. Until then, install both gems from the repository:
|
|
6
|
+
|
|
7
|
+
```ruby
|
|
8
|
+
gem "zard", github: "rigortype/zard"
|
|
9
|
+
gem "zard-doc", github: "rigortype/zard"
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
After publication, use the released pair:
|
|
13
|
+
|
|
14
|
+
```ruby
|
|
15
|
+
gem "zard", "~> 0.0.1"
|
|
16
|
+
gem "zard-doc", "~> 0.0.1"
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
```ruby
|
|
20
|
+
require "zard"
|
|
21
|
+
require "zard/doc"
|
|
22
|
+
|
|
23
|
+
document = Zard.parse(source, path: "lib/example.rb")
|
|
24
|
+
markdown = Zard::Doc.render(document)
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Descriptions may continue across plain comment lines until the next annotation or contract.
|
|
28
|
+
|
|
29
|
+
Run the linter against Ruby source files with:
|
|
30
|
+
|
|
31
|
+
```console
|
|
32
|
+
zard-doc lint lib
|
|
33
|
+
zard-doc lint --fail-on warning lib/example.rb
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Render Markdown to standard output with:
|
|
37
|
+
|
|
38
|
+
```console
|
|
39
|
+
zard-doc render lib
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Directories are searched recursively for Ruby source files. Files are processed in stable sorted order and duplicate paths are ignored.
|
|
43
|
+
Unreadable inputs are reported together; rendering never emits partial Markdown when any input cannot be read.
|
|
44
|
+
Use `-` as a path to read Ruby source from standard input.
|
|
45
|
+
|
|
46
|
+
`lint` exits with 0 when no diagnostic meets the configured failure threshold, 1 when a diagnostic meets it, and 2 for invalid usage or unreadable input. The default threshold is `error`; `--fail-on warning` also fails on warnings. `render` exits with 1 for error diagnostics, 2 for invalid usage or unreadable input, and 0 otherwise. Diagnostics go to standard error for `render`; lint diagnostics go to standard output.
|
data/exe/zard-doc
ADDED
data/lib/zard/doc/cli.rb
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "optparse"
|
|
4
|
+
require "zard/doc"
|
|
5
|
+
|
|
6
|
+
module Zard
|
|
7
|
+
module Doc
|
|
8
|
+
class CLI
|
|
9
|
+
SEVERITY_RANK = {error: 2, warning: 1, info: 0}.freeze
|
|
10
|
+
|
|
11
|
+
def self.run(argv, stdin: $stdin, stdout: $stdout, stderr: $stderr)
|
|
12
|
+
new(argv, stdin, stdout, stderr).run
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def initialize(argv, stdin, stdout, stderr)
|
|
16
|
+
@argv = argv.dup
|
|
17
|
+
@stdin = stdin
|
|
18
|
+
@stdout = stdout
|
|
19
|
+
@stderr = stderr
|
|
20
|
+
@fail_on = :error
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def run
|
|
24
|
+
return help if @argv.first == "--help" || @argv.first == "-h"
|
|
25
|
+
|
|
26
|
+
case @argv.shift
|
|
27
|
+
when "lint"
|
|
28
|
+
lint_command
|
|
29
|
+
when "render"
|
|
30
|
+
render_command
|
|
31
|
+
else
|
|
32
|
+
usage_error("Expected the lint or render command.")
|
|
33
|
+
end
|
|
34
|
+
rescue OptionParser::ParseError => error
|
|
35
|
+
usage_error(error.message)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
private
|
|
39
|
+
|
|
40
|
+
def lint_command
|
|
41
|
+
lint_option_parser.parse!(@argv)
|
|
42
|
+
return usage_error("Pass at least one Ruby source file.") if @argv.empty?
|
|
43
|
+
|
|
44
|
+
paths = source_paths(@argv)
|
|
45
|
+
return usage_error("No Ruby source files were found.") if paths.empty?
|
|
46
|
+
|
|
47
|
+
lint(paths)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def lint_option_parser
|
|
51
|
+
OptionParser.new do |parser|
|
|
52
|
+
parser.banner = usage
|
|
53
|
+
parser.on("--fail-on LEVEL", %w[error warning], "Minimum severity that exits unsuccessfully") do |level|
|
|
54
|
+
@fail_on = level.to_sym
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def render_command
|
|
60
|
+
OptionParser.new.parse!(@argv)
|
|
61
|
+
return usage_error("Pass at least one Ruby source file.") if @argv.empty?
|
|
62
|
+
|
|
63
|
+
paths = source_paths(@argv)
|
|
64
|
+
return usage_error("No Ruby source files were found.") if paths.empty?
|
|
65
|
+
|
|
66
|
+
render(paths)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def source_paths(inputs)
|
|
70
|
+
inputs.flat_map do |input|
|
|
71
|
+
File.directory?(input) ? Dir.glob(File.join(input, "**", "*.rb")).sort : input
|
|
72
|
+
end.uniq.sort
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def lint(paths)
|
|
76
|
+
failed = false
|
|
77
|
+
input_error = false
|
|
78
|
+
|
|
79
|
+
paths.each do |path|
|
|
80
|
+
source = read_source(path)
|
|
81
|
+
unless source
|
|
82
|
+
input_error = true
|
|
83
|
+
next
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
document = Zard.parse(source, path: path)
|
|
87
|
+
document.diagnostics.each do |diagnostic|
|
|
88
|
+
@stdout.puts format_diagnostic(diagnostic)
|
|
89
|
+
failed ||= failing?(diagnostic)
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
return 2 if input_error
|
|
94
|
+
|
|
95
|
+
failed ? 1 : 0
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def render(paths)
|
|
99
|
+
documents = paths.filter_map do |path|
|
|
100
|
+
source = read_source(path)
|
|
101
|
+
Zard.parse(source, path: path) if source
|
|
102
|
+
end
|
|
103
|
+
return 2 if documents.length != paths.length
|
|
104
|
+
|
|
105
|
+
diagnostics = documents.flat_map(&:diagnostics)
|
|
106
|
+
diagnostics.each { |diagnostic| @stderr.puts format_diagnostic(diagnostic) }
|
|
107
|
+
return 1 if diagnostics.any? { |diagnostic| diagnostic.severity == :error }
|
|
108
|
+
|
|
109
|
+
markdown = documents.map { |document| Zard::Doc.render(document) }.reject(&:empty?).join("\n")
|
|
110
|
+
@stdout.print markdown
|
|
111
|
+
0
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def read_source(path)
|
|
115
|
+
return @stdin.read if path == "-"
|
|
116
|
+
|
|
117
|
+
File.read(path)
|
|
118
|
+
rescue SystemCallError => error
|
|
119
|
+
@stderr.puts "#{path}: #{error.message}"
|
|
120
|
+
nil
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def failing?(diagnostic)
|
|
124
|
+
SEVERITY_RANK.fetch(diagnostic.severity) >= SEVERITY_RANK.fetch(@fail_on)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def format_diagnostic(diagnostic)
|
|
128
|
+
span = diagnostic.span
|
|
129
|
+
"#{span.path}:#{span.start_line}:#{span.start_column + 1}: #{diagnostic.severity} #{diagnostic.code} #{diagnostic.message}"
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def help
|
|
133
|
+
@stdout.puts usage
|
|
134
|
+
0
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def usage_error(message)
|
|
138
|
+
@stderr.puts message
|
|
139
|
+
@stderr.puts usage
|
|
140
|
+
2
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def usage
|
|
144
|
+
<<~USAGE.chomp
|
|
145
|
+
Usage:
|
|
146
|
+
zard-doc lint [--fail-on error|warning] PATH...
|
|
147
|
+
zard-doc render PATH...
|
|
148
|
+
USAGE
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
end
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Zard
|
|
4
|
+
module Doc
|
|
5
|
+
class Renderer
|
|
6
|
+
def self.render(document)
|
|
7
|
+
new(document).render
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def initialize(document)
|
|
11
|
+
@document = document
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def render
|
|
15
|
+
sections = @document.declarations.filter_map { |declaration| render_declaration(declaration) }
|
|
16
|
+
return "" if sections.empty?
|
|
17
|
+
|
|
18
|
+
"#{sections.join("\n\n")}\n"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
def render_declaration(declaration)
|
|
24
|
+
return unless declaration.visibility == :public
|
|
25
|
+
|
|
26
|
+
documentation = declaration.documentation.reject { |tag| tag.name == :raw }
|
|
27
|
+
return if documentation.empty?
|
|
28
|
+
|
|
29
|
+
parts = [heading(declaration)]
|
|
30
|
+
parts << "Superclass: `#{declaration.superclass}`." if declaration.superclass
|
|
31
|
+
parts << render_container_builder(declaration) if declaration.container_builder
|
|
32
|
+
append_mixins(parts, declaration)
|
|
33
|
+
parts << "Alias of `#{display_alias_target(declaration)}`." if declaration.alias_target
|
|
34
|
+
text = documentation.select { |tag| tag.name == :text }.map(&:description)
|
|
35
|
+
parts << text.join("\n") unless text.empty?
|
|
36
|
+
|
|
37
|
+
deprecated = documentation.select { |tag| tag.name == :deprecated }
|
|
38
|
+
parts << "### Deprecated\n\n#{deprecated.map(&:description).join("\n\n")}" unless deprecated.empty?
|
|
39
|
+
|
|
40
|
+
notes = documentation.select { |tag| tag.name == :note }
|
|
41
|
+
parts << "### Notes\n\n#{notes.map(&:description).join("\n\n")}" unless notes.empty?
|
|
42
|
+
|
|
43
|
+
examples = documentation.select { |tag| tag.name == :example }
|
|
44
|
+
parts << "### Examples\n\n#{examples.map(&:description).join("\n\n")}" unless examples.empty?
|
|
45
|
+
|
|
46
|
+
parameters = documentation.select { |tag| tag.name == :param }
|
|
47
|
+
unless parameters.empty?
|
|
48
|
+
items = parameters.map { |tag| list_item("`#{tag.subject}` — ", tag.description) }
|
|
49
|
+
parts << "### Parameters\n\n#{items.join("\n")}"
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
returns = documentation.select { |tag| tag.name == :return }
|
|
53
|
+
parts << "### Returns\n\n#{returns.map(&:description).join("\n\n")}" unless returns.empty?
|
|
54
|
+
|
|
55
|
+
documentation.select { |tag| tag.name == :option }.group_by(&:owner).each do |owner, options|
|
|
56
|
+
items = options.map { |tag| list_item("`#{tag.subject}` — ", tag.description) }
|
|
57
|
+
parts << "### Options for `#{owner}`\n\n#{items.join("\n")}"
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
raises = documentation.select { |tag| tag.name == :raise }
|
|
61
|
+
unless raises.empty?
|
|
62
|
+
items = raises.map { |tag| list_item("`#{tag.subject}` — ", tag.description) }
|
|
63
|
+
parts << "### Raises\n\n#{items.join("\n")}"
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
yield_parameters = documentation.select { |tag| tag.name == :yieldparam }
|
|
67
|
+
unless yield_parameters.empty?
|
|
68
|
+
items = yield_parameters.map { |tag| list_item("`#{tag.subject}` — ", tag.description) }
|
|
69
|
+
parts << "### Yield parameters\n\n#{items.join("\n")}"
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
yield_returns = documentation.select { |tag| tag.name == :yieldreturn }
|
|
73
|
+
parts << "### Yields\n\n#{yield_returns.map(&:description).join("\n\n")}" unless yield_returns.empty?
|
|
74
|
+
|
|
75
|
+
see_also = documentation.select { |tag| tag.name == :see }
|
|
76
|
+
unless see_also.empty?
|
|
77
|
+
items = see_also.map { |tag| list_item("", tag.description) }
|
|
78
|
+
parts << "### See also\n\n#{items.join("\n")}"
|
|
79
|
+
end
|
|
80
|
+
parts.join("\n\n")
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def heading(declaration)
|
|
84
|
+
return "## Alias `#{display_name(declaration)}`" if declaration.alias_target
|
|
85
|
+
|
|
86
|
+
case declaration.kind
|
|
87
|
+
when :class
|
|
88
|
+
"## Class `#{qualified_name(declaration)}`"
|
|
89
|
+
when :module
|
|
90
|
+
"## Module `#{qualified_name(declaration)}`"
|
|
91
|
+
when :constant
|
|
92
|
+
"## Constant `#{qualified_name(declaration)}`"
|
|
93
|
+
when :refinement
|
|
94
|
+
"## Refinement `#{refinement_owner(declaration)}`"
|
|
95
|
+
when :instance_attribute_reader, :singleton_attribute_reader
|
|
96
|
+
"## Attribute reader `#{display_name(declaration)}`"
|
|
97
|
+
when :instance_attribute_writer, :singleton_attribute_writer
|
|
98
|
+
"## Attribute writer `#{display_name(declaration)}`"
|
|
99
|
+
when :instance_attribute_accessor, :singleton_attribute_accessor
|
|
100
|
+
"## Attribute accessor `#{display_name(declaration)}`"
|
|
101
|
+
else
|
|
102
|
+
"## `#{display_name(declaration)}(#{declaration.parameters.join(", ")})`"
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def append_mixins(parts, declaration)
|
|
107
|
+
{include: "Includes", prepend: "Prepends", extend: "Extends"}.each do |kind, heading|
|
|
108
|
+
targets = declaration.mixins.select { |mixin| mixin.kind == kind }.map(&:target)
|
|
109
|
+
parts << "### #{heading}\n\n#{targets.map { |target| "- `#{target}`" }.join("\n")}" unless targets.empty?
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def render_container_builder(declaration)
|
|
114
|
+
builder = declaration.container_builder
|
|
115
|
+
label = if declaration.kind == :module
|
|
116
|
+
"Module builder"
|
|
117
|
+
else
|
|
118
|
+
"Class builder"
|
|
119
|
+
end
|
|
120
|
+
return "#{label}: `#{builder}`." unless builder.include?("\n")
|
|
121
|
+
|
|
122
|
+
"#{label}:\n\n```ruby\n#{dedent_continuation(builder)}\n```"
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def dedent_continuation(source)
|
|
126
|
+
first, *continuation = source.lines(chomp: true)
|
|
127
|
+
margins = continuation.reject { |line| line.strip.empty? }.map { |line| line[/\A[\t ]*/].length }
|
|
128
|
+
margin = margins.min || 0
|
|
129
|
+
[first, *continuation.map { |line| line[margin..] }].join("\n")
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def qualified_name(declaration)
|
|
133
|
+
[declaration.namespace, declaration.name].compact.join("::")
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def display_name(declaration)
|
|
137
|
+
if declaration.refinement
|
|
138
|
+
separator = declaration.kind.to_s.start_with?("singleton_") ? "." : "#"
|
|
139
|
+
return "#{refinement_owner(declaration)}#{separator}#{declaration.name}"
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
if declaration.kind.to_s.start_with?("singleton_")
|
|
143
|
+
owner = singleton_owner(declaration)
|
|
144
|
+
return owner ? "#{owner}.#{declaration.name}" : declaration.name
|
|
145
|
+
end
|
|
146
|
+
return declaration.name unless declaration.namespace
|
|
147
|
+
|
|
148
|
+
"#{declaration.namespace}##{declaration.name}"
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def display_alias_target(declaration)
|
|
152
|
+
if declaration.refinement
|
|
153
|
+
separator = declaration.kind.to_s.start_with?("singleton_") ? "." : "#"
|
|
154
|
+
return "#{refinement_owner(declaration)}#{separator}#{declaration.alias_target}"
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
if declaration.kind.to_s.start_with?("singleton_")
|
|
158
|
+
owner = singleton_owner(declaration)
|
|
159
|
+
return owner ? "#{owner}.#{declaration.alias_target}" : declaration.alias_target
|
|
160
|
+
end
|
|
161
|
+
return declaration.alias_target unless declaration.namespace
|
|
162
|
+
|
|
163
|
+
"#{declaration.namespace}##{declaration.alias_target}"
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def singleton_owner(declaration)
|
|
167
|
+
return declaration.receiver unless declaration.receiver.nil? || declaration.receiver == "self"
|
|
168
|
+
|
|
169
|
+
declaration.namespace || declaration.receiver
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def refinement_owner(declaration)
|
|
173
|
+
namespace = declaration.namespace
|
|
174
|
+
target = declaration.refinement || declaration.name
|
|
175
|
+
namespace ? "#{namespace}[#{target}]" : "[#{target}]"
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def list_item(prefix, description)
|
|
179
|
+
first, *continuation = description.split("\n", -1)
|
|
180
|
+
lines = ["- #{prefix}#{first}"]
|
|
181
|
+
continuation.each { |line| lines << (line.empty? ? "" : " #{line}") }
|
|
182
|
+
lines.join("\n")
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
end
|
data/lib/zard/doc.rb
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "zard"
|
|
4
|
+
require_relative "doc/version"
|
|
5
|
+
require_relative "doc/renderer"
|
|
6
|
+
|
|
7
|
+
module Zard
|
|
8
|
+
module Doc
|
|
9
|
+
def self.render(document)
|
|
10
|
+
Renderer.render(document)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
private_constant :Renderer
|
|
14
|
+
end
|
|
15
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: zard-doc
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- USAMI Kenta
|
|
8
|
+
bindir: exe
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: zard
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: 0.0.1
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: 0.0.1
|
|
26
|
+
description: zard-doc renders API documentation from the versioned ZARD document model.
|
|
27
|
+
email:
|
|
28
|
+
- tadsan@zonu.me
|
|
29
|
+
executables:
|
|
30
|
+
- zard-doc
|
|
31
|
+
extensions: []
|
|
32
|
+
extra_rdoc_files: []
|
|
33
|
+
files:
|
|
34
|
+
- LICENSE
|
|
35
|
+
- README.md
|
|
36
|
+
- exe/zard-doc
|
|
37
|
+
- lib/zard/doc.rb
|
|
38
|
+
- lib/zard/doc/cli.rb
|
|
39
|
+
- lib/zard/doc/renderer.rb
|
|
40
|
+
- lib/zard/doc/version.rb
|
|
41
|
+
homepage: https://github.com/rigortype/zard
|
|
42
|
+
licenses:
|
|
43
|
+
- MPL-2.0
|
|
44
|
+
metadata:
|
|
45
|
+
allowed_push_host: https://rubygems.org
|
|
46
|
+
homepage_uri: https://github.com/rigortype/zard
|
|
47
|
+
rubygems_mfa_required: 'true'
|
|
48
|
+
source_code_uri: https://github.com/rigortype/zard
|
|
49
|
+
rdoc_options: []
|
|
50
|
+
require_paths:
|
|
51
|
+
- lib
|
|
52
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
53
|
+
requirements:
|
|
54
|
+
- - ">="
|
|
55
|
+
- !ruby/object:Gem::Version
|
|
56
|
+
version: 3.2.0
|
|
57
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - ">="
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '0'
|
|
62
|
+
requirements: []
|
|
63
|
+
rubygems_version: 4.0.20
|
|
64
|
+
specification_version: 4
|
|
65
|
+
summary: Markdown API documentation for ZARD
|
|
66
|
+
test_files: []
|