jaxrsdoc 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.
- data/bin/jaxrsdoc +70 -0
- data/lib/annotations.rb +104 -0
- data/lib/jaxrsdoc_version.rb +3 -0
- data/lib/parse.rb +91 -0
- data/lib/site.rb +60 -0
- data/lib/templates.rb +208 -0
- data/site/bootstrap.css +4983 -0
- data/site/jaxrsdoc.css +19 -0
- metadata +53 -0
data/bin/jaxrsdoc
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require File.expand_path("../../lib/parse.rb", __FILE__)
|
3
|
+
require File.expand_path("../../lib/site.rb", __FILE__)
|
4
|
+
require 'optparse'
|
5
|
+
require "rexml/document"
|
6
|
+
|
7
|
+
options = {}
|
8
|
+
optparse = OptionParser.new do |opts|
|
9
|
+
opts.banner = "USAGE\n jaxrsdoc [options] source_location"
|
10
|
+
opts.separator "\nOPTIONS\n"
|
11
|
+
|
12
|
+
options[:pattern] = "*Resource.java"
|
13
|
+
opts.on( '-p', '--pattern PATTERN', 'Naming pattern of your Jaxrs annotated files java resources. Default is: "*Resource.java".' ) do |pattern|
|
14
|
+
options[:pattern] = pattern
|
15
|
+
end
|
16
|
+
|
17
|
+
opts.on( '-m', '--maven', 'Indicates a maven project. Project name & version will be derived the pom.xml at the directory level' ) do |maven|
|
18
|
+
options[:maven] = true
|
19
|
+
end
|
20
|
+
|
21
|
+
opts.on( '-a', '--artifact ARTIFACT', 'Name of the artifact/project/module to be included on the website banner.' ) do |artifact_name|
|
22
|
+
options[:artifact_name] = artifact_name
|
23
|
+
end
|
24
|
+
|
25
|
+
opts.on( '-v', '--version VERSION', 'Version of your artifact/project/module to be included on the website banner.' ) do |artifact_version|
|
26
|
+
options[:artifact_version] = artifact_version
|
27
|
+
end
|
28
|
+
|
29
|
+
opts.on( '-h', '--help', 'Display this screen' ) do
|
30
|
+
puts opts
|
31
|
+
exit
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
begin
|
36
|
+
optparse.parse!
|
37
|
+
rescue OptionParser::InvalidOption, OptionParser::InvalidArgument, OptionParser::MissingArgument
|
38
|
+
puts "#{$!.message}"
|
39
|
+
puts "try 'jaxrsdoc -h' for more information"
|
40
|
+
exit
|
41
|
+
end
|
42
|
+
|
43
|
+
resources_location = ARGV.first
|
44
|
+
|
45
|
+
puts "Looking files recursively at #{resources_location}"
|
46
|
+
matched_files = Dir.glob("#{resources_location}/**/#{options[:pattern]}").select{ |entry| File.file?(entry) }
|
47
|
+
puts "Found #{matched_files.size} files matching '#{options[:pattern]}'"
|
48
|
+
|
49
|
+
processed_resources = matched_files.map {|file|
|
50
|
+
JaxrsDoc::ResourceParser.parse(File.new(file))
|
51
|
+
}.select {|resource| resource.valid? and not resource.nil? }
|
52
|
+
puts "Processed #{processed_resources.size} files with a @Path type annotation"
|
53
|
+
|
54
|
+
project_version = options[:artifact_version]
|
55
|
+
project_name = options[:artifact_name]
|
56
|
+
|
57
|
+
if(options[:maven]) then
|
58
|
+
puts "Looking for a pom.xml file at #{resources_location}"
|
59
|
+
pom_xml = Dir.glob("#{resources_location}/pom.xml").first
|
60
|
+
pom = REXML::Document.new File.new(pom_xml)
|
61
|
+
project_name = pom.elements["//artifactId"].first
|
62
|
+
project_version = pom.elements["//version"].first
|
63
|
+
puts "Found maven project with name: #{project_name}, version: #{project_version}"
|
64
|
+
end
|
65
|
+
|
66
|
+
output_dir = JaxrsDoc::Site.new(processed_resources, Dir.pwd, {:project_version => project_version, :project_name => project_name}).generate
|
67
|
+
|
68
|
+
puts "Site generated. Open #{output_dir.path}/index.html"
|
69
|
+
|
70
|
+
|
data/lib/annotations.rb
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
module JaxrsDoc
|
2
|
+
|
3
|
+
class Resource
|
4
|
+
include Comparable
|
5
|
+
|
6
|
+
attr_reader :name, :description, :params_descriptions, :path, :verbs, :gets, :posts, :puts, :deletes, :consumes
|
7
|
+
|
8
|
+
def initialize(file_name, type_annotations, verbs_annotations = {}, type_description = nil, params_descriptions = {})
|
9
|
+
@name = file_name
|
10
|
+
@description = type_description
|
11
|
+
@params_descriptions = params_descriptions
|
12
|
+
@path = type_annotations.annotations.find {|a| a.name.eql?"Path"}
|
13
|
+
@consumes = type_annotations.annotations.find {|a| a.name.eql?"Consumes"}
|
14
|
+
@gets = verbs_annotations[:gets]
|
15
|
+
@posts = verbs_annotations[:posts]
|
16
|
+
@puts = verbs_annotations[:puts]
|
17
|
+
@deletes = verbs_annotations[:deletes]
|
18
|
+
@verbs = verbs_annotations
|
19
|
+
end
|
20
|
+
|
21
|
+
def valid?
|
22
|
+
not @path.nil?
|
23
|
+
end
|
24
|
+
|
25
|
+
def add_param_description(param_description)
|
26
|
+
@params_descriptions.update(param_description)
|
27
|
+
end
|
28
|
+
|
29
|
+
def <=>(another)
|
30
|
+
path.value <=> another.path.value
|
31
|
+
end
|
32
|
+
|
33
|
+
def to_s
|
34
|
+
"#{@name} [#{@path.value}]"
|
35
|
+
end
|
36
|
+
|
37
|
+
# Support ERB templating of member data.
|
38
|
+
def get_binding
|
39
|
+
binding
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
class AnnotationsGroup
|
45
|
+
|
46
|
+
attr_reader :annotations
|
47
|
+
|
48
|
+
def initialize(annotations = [])
|
49
|
+
@annotations = Array.new(annotations)
|
50
|
+
end
|
51
|
+
|
52
|
+
def method_missing(method_name, *args)
|
53
|
+
if(method_name.to_s.include?"params")
|
54
|
+
@annotations.select{|a| /\b(Form|FormData|Query)Param\b/ =~ a.name }
|
55
|
+
else
|
56
|
+
@annotations.find {|a| method_name.to_s.eql?(a.name.downcase) }
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def empty?
|
61
|
+
@annotations.empty?
|
62
|
+
end
|
63
|
+
|
64
|
+
def size
|
65
|
+
@annotations.size
|
66
|
+
end
|
67
|
+
|
68
|
+
def to_s
|
69
|
+
@annotations.to_s
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
class Annotation
|
76
|
+
|
77
|
+
attr_reader :name, :values, :value
|
78
|
+
|
79
|
+
def initialize(annotation_text)
|
80
|
+
@text = annotation_text.strip
|
81
|
+
@name = @text.delete("@").split("(")[0]
|
82
|
+
parse_values
|
83
|
+
end
|
84
|
+
|
85
|
+
def to_s
|
86
|
+
@text
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
def parse_values
|
92
|
+
@values = []
|
93
|
+
if(matches = /\((.*)\)/.match(@text))
|
94
|
+
tokens = matches[1].split(",")
|
95
|
+
tokens.each { |v|
|
96
|
+
@values << v.gsub(/\"|'/, "").strip
|
97
|
+
}
|
98
|
+
@value = tokens.first.gsub(/\"|'/, "").strip
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
data/lib/parse.rb
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
require File.expand_path("../annotations.rb", __FILE__)
|
2
|
+
|
3
|
+
module JaxrsDoc
|
4
|
+
|
5
|
+
module AnnotationScanner
|
6
|
+
|
7
|
+
JAXRS_ANNOTATIONS = %w[ ApplicationPath Consumes CookieParam DefaultValue
|
8
|
+
DELETE Encoded FormParam FormDataParam GET HEAD HeaderParam
|
9
|
+
HttpMethod MatrixParam OPTIONS Path PathParam
|
10
|
+
POST Produces PUT QueryParam ]
|
11
|
+
|
12
|
+
def self.scan_annotations(text)
|
13
|
+
annotations = []
|
14
|
+
text.scan(jaxrs_annotations_regexp) {|s| annotations << JaxrsDoc::Annotation.new(s.first)}
|
15
|
+
JaxrsDoc::AnnotationsGroup.new(annotations)
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def self.jaxrs_annotations_regexp
|
21
|
+
regexp = JAXRS_ANNOTATIONS.map { |a|
|
22
|
+
["#{a}(?=[[:space:]])", "#{a}\\(?.*?\\)"]
|
23
|
+
}
|
24
|
+
Regexp.new("@(#{regexp.join('|')})")
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
module ParamDescriptionScanner
|
30
|
+
|
31
|
+
def self.scan_params_descriptions(text)
|
32
|
+
params_descriptions = Hash.new("")
|
33
|
+
text.each_line { |line|
|
34
|
+
if(param_index = line.index("@param"))
|
35
|
+
param_name, param_desc = line[(param_index + 6)..-1].split(" ", 2);
|
36
|
+
params_descriptions.store(param_name, param_desc)
|
37
|
+
end
|
38
|
+
}
|
39
|
+
params_descriptions
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
module ResourceParser
|
45
|
+
include AnnotationScanner
|
46
|
+
|
47
|
+
def self.parse(file)
|
48
|
+
@filename = File.basename(file.path)
|
49
|
+
parse_content(file.read)
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.parse_content(text)
|
53
|
+
verbs_annotations = {:gets => [], :posts => [], :puts => [], :deletes => []}
|
54
|
+
descriptions = {}
|
55
|
+
java_sections = text.split(/(?<=\s)({)/);
|
56
|
+
resource_head_section = java_sections.shift
|
57
|
+
type_annotations = AnnotationScanner.scan_annotations(resource_head_section)
|
58
|
+
descriptions.update(ParamDescriptionScanner.scan_params_descriptions(resource_head_section))
|
59
|
+
type_description = parse_resource_description(resource_head_section)
|
60
|
+
java_sections.each { |section|
|
61
|
+
group = AnnotationScanner.scan_annotations(section)
|
62
|
+
descriptions.update(ParamDescriptionScanner.scan_params_descriptions(section))
|
63
|
+
unless group.empty?
|
64
|
+
verbs_annotations[:gets] << group if(group.get)
|
65
|
+
verbs_annotations[:posts] << group if(group.post)
|
66
|
+
verbs_annotations[:puts] << group if(group.put)
|
67
|
+
verbs_annotations[:deletes] << group if(group.delete)
|
68
|
+
end
|
69
|
+
}
|
70
|
+
JaxrsDoc::Resource.new(@filename, type_annotations, verbs_annotations, type_description, descriptions)
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
def self.parse_resource_description(head_text_section)
|
76
|
+
from_package_only_head_section = head_text_section.each_line.drop_while {|line|
|
77
|
+
not line.strip.start_with?("package")
|
78
|
+
}.join
|
79
|
+
|
80
|
+
if (description_match = /^\/\*\*(.+)\*\/$/m.match(from_package_only_head_section))
|
81
|
+
full_text = description_match[1].gsub("*", "")
|
82
|
+
description = ""
|
83
|
+
full_text.each_line { |line|
|
84
|
+
description << line unless line.include?("@param")
|
85
|
+
}
|
86
|
+
description
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
end
|
data/lib/site.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
require File.expand_path("../templates.rb", __FILE__)
|
2
|
+
require 'erb'
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
module JaxrsDoc
|
6
|
+
|
7
|
+
class Site
|
8
|
+
|
9
|
+
attr_reader :resources, :project_version, :project_name, :output_dir
|
10
|
+
|
11
|
+
def initialize(resources, output_location, options = {})
|
12
|
+
@resources = resources.sort!
|
13
|
+
@project_version = options[:project_version]
|
14
|
+
@project_name = options[:project_name]
|
15
|
+
make_output_dir(output_location)
|
16
|
+
copy_resources_to_output_dir
|
17
|
+
end
|
18
|
+
|
19
|
+
def generate
|
20
|
+
@resources.each { |resource|
|
21
|
+
File.open(resource_file_path(resource.name), "w") { |f|
|
22
|
+
content = ERB.new(JaxrsDoc::Templates.get_resource_page).result(binding)
|
23
|
+
f.syswrite(content)
|
24
|
+
}
|
25
|
+
}
|
26
|
+
|
27
|
+
File.open(index_file_path, "w") { |f|
|
28
|
+
content = ERB.new(JaxrsDoc::Templates.get_index_page).result(binding)
|
29
|
+
f.syswrite(content)
|
30
|
+
}
|
31
|
+
@output_dir
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def resource_file_path(resource_name)
|
37
|
+
File.join(@output_dir.path, "#{resource_name}.html")
|
38
|
+
end
|
39
|
+
|
40
|
+
def index_file_path
|
41
|
+
File.join(@output_dir.path, "index.html")
|
42
|
+
end
|
43
|
+
|
44
|
+
def make_output_dir(output_location)
|
45
|
+
output_path = "#{output_location}"
|
46
|
+
output_path << "/jaxrsdoc"
|
47
|
+
output_path << "/#{@project_name}" unless @project_name.nil?
|
48
|
+
output_path << "/#{@project_version}" unless @project_version.nil?
|
49
|
+
FileUtils.mkdir_p(output_path)
|
50
|
+
@output_dir = Dir.new(output_path)
|
51
|
+
end
|
52
|
+
|
53
|
+
def copy_resources_to_output_dir
|
54
|
+
bootstrap_file_path = File.expand_path("../../site/bootstrap.css", __FILE__)
|
55
|
+
jaxrsdoc_css_file_path = File.expand_path("../../site/jaxrsdoc.css", __FILE__)
|
56
|
+
FileUtils.cp(bootstrap_file_path, File.join(@output_dir.path, "bootstrap.css"))
|
57
|
+
FileUtils.cp(jaxrsdoc_css_file_path, File.join(@output_dir.path, "jaxrsdoc.css"))
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/lib/templates.rb
ADDED
@@ -0,0 +1,208 @@
|
|
1
|
+
module JaxrsDoc
|
2
|
+
|
3
|
+
module Templates
|
4
|
+
|
5
|
+
def self.get_index_page
|
6
|
+
%q{
|
7
|
+
<html>
|
8
|
+
<head>
|
9
|
+
<link rel="stylesheet" type="text/css" href="bootstrap.css" />
|
10
|
+
<link rel="stylesheet" type="text/css" href="jaxrsdoc.css" />
|
11
|
+
</head>
|
12
|
+
<body>
|
13
|
+
<div class="navbar">
|
14
|
+
<div class="navbar-inner">
|
15
|
+
<div class="container">
|
16
|
+
<a class="brand" href="#"><%= @project_name %> <%= @project_version %></a>
|
17
|
+
<ul class="nav">
|
18
|
+
<li class="active"><a href="index.html">API index</a></li>
|
19
|
+
</ul>
|
20
|
+
<p class="navbar-text pull-right">Last update <%= Time.now.strftime("%d %B - %H:%M:%S") %></p>
|
21
|
+
</div>
|
22
|
+
</div>
|
23
|
+
</div>
|
24
|
+
<div class="container">
|
25
|
+
<% @resources.each_slice(20) do |big_packets_of_resources| %>
|
26
|
+
<div class="row">
|
27
|
+
<% big_packets_of_resources.each_slice(10) do |small_packets_of_resources|%>
|
28
|
+
<div class="span6">
|
29
|
+
<pre><ul><% small_packets_of_resources.each do |resource|%><li><a href="<%= resource.name %>.html"> <% if resource.path %><%= resource.path.value %><% end %></a></li><% end%></ul></pre>
|
30
|
+
</div>
|
31
|
+
<% end %>
|
32
|
+
</div>
|
33
|
+
<% end%>
|
34
|
+
<footer class="modal-footer"><span>Powered by <a href="https://github.com/simcap/jaxrsdoc">Jaxrsdoc</a></span></footer>
|
35
|
+
</div>
|
36
|
+
<body>
|
37
|
+
</html>
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.get_resource_page
|
42
|
+
%q{
|
43
|
+
<html>
|
44
|
+
<head>
|
45
|
+
<link rel="stylesheet" type="text/css" href="bootstrap.css" />
|
46
|
+
<link rel="stylesheet" type="text/css" href="jaxrsdoc.css" />
|
47
|
+
</head>
|
48
|
+
<body>
|
49
|
+
<div class="navbar">
|
50
|
+
<div class="navbar-inner">
|
51
|
+
<div class="container">
|
52
|
+
<a class="brand" href="#"><%= @project_name %> <%= @project_version %></a>
|
53
|
+
<ul class="nav">
|
54
|
+
<li class="active"><a href="index.html">API index</a></li>
|
55
|
+
</ul>
|
56
|
+
<p class="navbar-text pull-right">Updated <%= Time.now.strftime("%d %B - %H:%M:%S") %></p>
|
57
|
+
</div>
|
58
|
+
</div>
|
59
|
+
</div>
|
60
|
+
|
61
|
+
<div class="container">
|
62
|
+
|
63
|
+
<div class="page-header">
|
64
|
+
<h1><% if resource.path %><%= resource.path.value %><% end %><pre class="pull-right"><%= resource.name %></pre></h1>
|
65
|
+
</div>
|
66
|
+
|
67
|
+
<% if resource.description %>
|
68
|
+
<div>
|
69
|
+
<pre><%= resource.description %></pre>
|
70
|
+
</div>
|
71
|
+
<% end %>
|
72
|
+
|
73
|
+
<% resource.gets.each do |annot_group| %>
|
74
|
+
<div class="row">
|
75
|
+
<div class="get span12">
|
76
|
+
<button class="btn btn-success pull-left disabled" href="#"><%= annot_group.get.name %></button>
|
77
|
+
<h3 class="pagination-centered"><% if annot_group.path %> <%= annot_group.path.value %> <% end %></h3>
|
78
|
+
</div>
|
79
|
+
</div>
|
80
|
+
|
81
|
+
<% unless annot_group.queryparams.empty? %>
|
82
|
+
<div class="row">
|
83
|
+
<div class="span12">
|
84
|
+
<table class="table table-bordered table-striped">
|
85
|
+
<colgroup>
|
86
|
+
<col class="span1">
|
87
|
+
</colgroup>
|
88
|
+
<thead>
|
89
|
+
<tr><th>Parameter</th><th>Description</th></tr>
|
90
|
+
</thead>
|
91
|
+
<tbody>
|
92
|
+
<% annot_group.queryparams.each do |param| %>
|
93
|
+
<tr>
|
94
|
+
<td><%= param.value %></td>
|
95
|
+
<td><%= resource.params_descriptions[param.value] %></td>
|
96
|
+
</tr>
|
97
|
+
<% end %>
|
98
|
+
</tbody>
|
99
|
+
</table>
|
100
|
+
</div>
|
101
|
+
</div>
|
102
|
+
<% end %>
|
103
|
+
<% end %>
|
104
|
+
|
105
|
+
<% resource.posts.each do |annot_group| %>
|
106
|
+
<div class="row">
|
107
|
+
<div class="post span12">
|
108
|
+
<button class="btn btn-info pull-left disabled" href="#"><%= annot_group.post.name %></button>
|
109
|
+
<h3 class="pagination-centered"><% if annot_group.path %> <%= annot_group.path.value %> <% end %></h3>
|
110
|
+
</div>
|
111
|
+
</div>
|
112
|
+
|
113
|
+
<% unless annot_group.params.empty? %>
|
114
|
+
<div class="row">
|
115
|
+
<div class="span12">
|
116
|
+
<table class="table table-bordered table-striped">
|
117
|
+
<colgroup>
|
118
|
+
<col class="span1">
|
119
|
+
</colgroup>
|
120
|
+
<thead>
|
121
|
+
<tr><th>Parameter</th><th>Description</th></tr>
|
122
|
+
</thead>
|
123
|
+
<tbody>
|
124
|
+
<% annot_group.params.each do |param| %>
|
125
|
+
<tr>
|
126
|
+
<td><%= param.value %></td>
|
127
|
+
<td><%= resource.params_descriptions[param.value] %></td>
|
128
|
+
</tr>
|
129
|
+
<% end %>
|
130
|
+
</tbody>
|
131
|
+
</table>
|
132
|
+
</div>
|
133
|
+
</div>
|
134
|
+
<% end %>
|
135
|
+
<% end %>
|
136
|
+
|
137
|
+
<% resource.puts.each do |annot_group| %>
|
138
|
+
<div class="row">
|
139
|
+
<div class="put span12">
|
140
|
+
<button class="btn btn-warning pull-left disabled" href="#"><%= annot_group.put.name %></button>
|
141
|
+
<h3 class="pagination-centered"><% if annot_group.path %> <%= annot_group.path.value %> <% end %></h3>
|
142
|
+
</div>
|
143
|
+
</div>
|
144
|
+
|
145
|
+
<% unless annot_group.params.empty? %>
|
146
|
+
<div class="row">
|
147
|
+
<div class="span12">
|
148
|
+
<table class="table table-bordered table-striped">
|
149
|
+
<colgroup>
|
150
|
+
<col class="span1">
|
151
|
+
</colgroup>
|
152
|
+
<thead>
|
153
|
+
<tr><th>Parameter</th><th>Description</th></tr>
|
154
|
+
</thead>
|
155
|
+
<tbody>
|
156
|
+
<% annot_group.params.each do |param| %>
|
157
|
+
<tr>
|
158
|
+
<td><%= param.value %></td>
|
159
|
+
<td><%= resource.params_descriptions[param.value] %></td>
|
160
|
+
</tr>
|
161
|
+
<% end %>
|
162
|
+
</tbody>
|
163
|
+
</table>
|
164
|
+
</div>
|
165
|
+
</div>
|
166
|
+
<% end %>
|
167
|
+
<% end %>
|
168
|
+
|
169
|
+
<% resource.deletes.each do |annot_group| %>
|
170
|
+
<div class="row">
|
171
|
+
<div class="post span12">
|
172
|
+
<button class="btn btn-danger pull-left disabled" href="#"><%= annot_group.delete.name %></button>
|
173
|
+
<h3 class="pagination-centered"><% if annot_group.path %> <%= annot_group.path.value %> <% end %></h3>
|
174
|
+
</div>
|
175
|
+
</div>
|
176
|
+
|
177
|
+
<% unless annot_group.params.empty? %>
|
178
|
+
<div class="row">
|
179
|
+
<div class="span12">
|
180
|
+
<table class="table table-bordered table-striped">
|
181
|
+
<colgroup>
|
182
|
+
<col class="span1">
|
183
|
+
</colgroup>
|
184
|
+
<thead>
|
185
|
+
<tr><th>Parameter</th><th>Description</th></tr>
|
186
|
+
</thead>
|
187
|
+
<tbody>
|
188
|
+
<% annot_group.params.each do |param| %>
|
189
|
+
<tr>
|
190
|
+
<td><%= param.value %></td>
|
191
|
+
<td><%= resource.params_descriptions[param.value] %></td>
|
192
|
+
</tr>
|
193
|
+
<% end %>
|
194
|
+
</tbody>
|
195
|
+
</table>
|
196
|
+
</div>
|
197
|
+
</div>
|
198
|
+
<% end %>
|
199
|
+
<% end %>
|
200
|
+
|
201
|
+
|
202
|
+
</div>
|
203
|
+
<body>
|
204
|
+
</html>
|
205
|
+
}
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|