jaxrsdoc 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|