yard-lucid 0.1.0

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.
Files changed (73) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +12 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +5 -0
  5. data/CODE_OF_CONDUCT.md +74 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +87 -0
  9. data/Rakefile +6 -0
  10. data/bin/console +13 -0
  11. data/bin/setup +8 -0
  12. data/lib/docserver/default/fulldoc/html/js/lucid.js +69 -0
  13. data/lib/docserver/default/layout/html/headers.erb +13 -0
  14. data/lib/docserver/doc_server/full_list/html/full_list.erb +37 -0
  15. data/lib/docserver/doc_server/full_list/html/setup.rb +19 -0
  16. data/lib/lucid/gherkin_repr.rb +307 -0
  17. data/lib/templates/default/feature/html/docstring.erb +3 -0
  18. data/lib/templates/default/feature/html/feature.erb +39 -0
  19. data/lib/templates/default/feature/html/no_steps_defined.erb +1 -0
  20. data/lib/templates/default/feature/html/outline.erb +52 -0
  21. data/lib/templates/default/feature/html/scenario.erb +52 -0
  22. data/lib/templates/default/feature/html/setup.rb +51 -0
  23. data/lib/templates/default/feature/html/steps.erb +37 -0
  24. data/lib/templates/default/feature/html/table.erb +19 -0
  25. data/lib/templates/default/featuredirectory/html/alpha_table.erb +30 -0
  26. data/lib/templates/default/featuredirectory/html/directory.erb +30 -0
  27. data/lib/templates/default/featuredirectory/html/setup.rb +41 -0
  28. data/lib/templates/default/featuretags/html/namespace.erb +127 -0
  29. data/lib/templates/default/featuretags/html/setup.rb +33 -0
  30. data/lib/templates/default/fulldoc/html/css/lucid.css +224 -0
  31. data/lib/templates/default/fulldoc/html/directories.erb +27 -0
  32. data/lib/templates/default/fulldoc/html/full_list_featuredirectories.erb +11 -0
  33. data/lib/templates/default/fulldoc/html/full_list_features.erb +36 -0
  34. data/lib/templates/default/fulldoc/html/full_list_stepdefinitions.erb +20 -0
  35. data/lib/templates/default/fulldoc/html/full_list_steps.erb +20 -0
  36. data/lib/templates/default/fulldoc/html/full_list_tags.erb +16 -0
  37. data/lib/templates/default/fulldoc/html/js/lucid.js +284 -0
  38. data/lib/templates/default/fulldoc/html/setup.rb +199 -0
  39. data/lib/templates/default/layout/html/setup.rb +111 -0
  40. data/lib/templates/default/specifications/html/alpha_table.erb +26 -0
  41. data/lib/templates/default/specifications/html/setup.rb +49 -0
  42. data/lib/templates/default/specifications/html/specifications.erb +46 -0
  43. data/lib/templates/default/steptransformers/html/header.erb +12 -0
  44. data/lib/templates/default/steptransformers/html/index.erb +9 -0
  45. data/lib/templates/default/steptransformers/html/setup.rb +92 -0
  46. data/lib/templates/default/steptransformers/html/transformers.erb +74 -0
  47. data/lib/templates/default/steptransformers/html/undefinedsteps.erb +26 -0
  48. data/lib/templates/default/tag/html/alpha_table.erb +32 -0
  49. data/lib/templates/default/tag/html/setup.rb +26 -0
  50. data/lib/templates/default/tag/html/tag.erb +31 -0
  51. data/lib/yard/code_objects/lucid/base.rb +23 -0
  52. data/lib/yard/code_objects/lucid/feature.rb +12 -0
  53. data/lib/yard/code_objects/lucid/namespace_object.rb +43 -0
  54. data/lib/yard/code_objects/lucid/scenario.rb +20 -0
  55. data/lib/yard/code_objects/lucid/scenario_outline.rb +66 -0
  56. data/lib/yard/code_objects/lucid/step.rb +32 -0
  57. data/lib/yard/code_objects/lucid/tag.rb +21 -0
  58. data/lib/yard/code_objects/step_definition.rb +3 -0
  59. data/lib/yard/code_objects/step_transform.rb +3 -0
  60. data/lib/yard/code_objects/step_transformer.rb +85 -0
  61. data/lib/yard/handlers/lucid/base.rb +19 -0
  62. data/lib/yard/handlers/lucid/feature_handler.rb +102 -0
  63. data/lib/yard/handlers/step_definition_handler.rb +67 -0
  64. data/lib/yard/handlers/step_transform_handler.rb +28 -0
  65. data/lib/yard/parser/lucid/feature.rb +58 -0
  66. data/lib/yard/server/adapter.rb +32 -0
  67. data/lib/yard/server/commands/list_command.rb +25 -0
  68. data/lib/yard/server/router.rb +23 -0
  69. data/lib/yard/templates/helpers/base_helper.rb +22 -0
  70. data/lib/yard-lucid/version.rb +3 -0
  71. data/lib/yard-lucid.rb +36 -0
  72. data/yard-lucid.gemspec +38 -0
  73. metadata +215 -0
@@ -0,0 +1,111 @@
1
+ def init
2
+ super
3
+ end
4
+
5
+ # Append yard-lucid stylesheet to yard core stylesheets
6
+ def stylesheets
7
+ super + %w(css/lucid.css)
8
+ end
9
+
10
+ # Append yard-lucid javascript to yard core javascripts
11
+ def javascripts
12
+ super + %w(js/lucid.js)
13
+ end
14
+
15
+ # Append yard-lucid specific menus 'features' and 'tags'
16
+ #
17
+ # 'features' and 'tags' are enabled by default.
18
+ #
19
+ # 'step definitions' and 'steps' may be enabled by setting up a value in
20
+ # yard configuration file '~/.yard/config'
21
+ #
22
+ # @example `~/.yard.config`
23
+ # yard-lucid:
24
+ # menus: [ 'features', 'directories', 'tags', 'step definitions', 'steps' ]
25
+ def menu_lists
26
+ current_menu_lists.map { |menu_name| yard_lucid_menus[menu_name] }.compact + super
27
+ end
28
+
29
+ # By default we want to display the 'features' and 'tags' menu but we will allow
30
+ # the YARD configuration to override that functionality.
31
+ def current_menu_lists
32
+ @current_menu_lists ||= begin
33
+ menus = [ "features", "tags" ]
34
+
35
+ if YARD::Config.options["yard-lucid"] and YARD::Config.options["yard-lucid"]["menus"]
36
+ menus = YARD::Config.options["yard-lucid"]["menus"]
37
+ end
38
+
39
+ menus
40
+ end
41
+ end
42
+
43
+ # When a menu is specified in the yard configuration file, this hash contains
44
+ # the details about the menu necessary for it to be displayed.
45
+ #
46
+ # @see #menu_lists
47
+ def yard_lucid_menus
48
+ { "features" => { :type => 'feature', :title => 'Features', :search_title => 'Features' },
49
+ "directories" => { :type => 'featuredirectories', :title => 'Features by Directory', :search_title => 'Features by Directory' },
50
+ "tags" => { :type => 'tag', :title => 'Tags', :search_title => 'Tags' },
51
+ "step definitions" => { :type => 'stepdefinition', :title => 'Step Definitions', :search_title => 'Step Defs' },
52
+ "steps" => { :type => 'step', :title => 'Steps', :search_title => 'Steps' } }
53
+ end
54
+
55
+ # This method overrides YARD's default layout template's layout method.
56
+ #
57
+ # The existing YARD layout method generates the url for the nav menu on the left
58
+ # side. For Yard-Lucid objects this will default to the class_list.html.
59
+ # which is not what we want for features, tags, and so forth.
60
+ #
61
+ # So we override this method and put in some additional logic to figure out the
62
+ # correct list to appear in the search. This can be particularly tricky because
63
+ #
64
+ # This method removes the namespace from the root node, generates the class list,
65
+ # and then adds it back into the root node.
66
+ def layout
67
+ @nav_url = url_for_list(!@file || options.index ? 'class' : 'file')
68
+
69
+ if is_yard_lucid_object?(object)
70
+ @nav_url = rewrite_nav_url(@nav_url)
71
+ end
72
+
73
+ if !object || object.is_a?(String)
74
+ @path = nil
75
+ elsif @file
76
+ @path = @file.path
77
+ elsif !object.is_a?(YARD::CodeObjects::NamespaceObject)
78
+ @path = object.parent.path
79
+ else
80
+ @path = object.path
81
+ end
82
+
83
+ erb(:layout)
84
+ end
85
+
86
+ # Determine if the object happens to be a CodeObject defined in this gem.
87
+ #
88
+ # Quite a few of the classes/modules defined here are not object that we
89
+ # would never want to display but it's alright if we match on them.
90
+ def is_yard_lucid_object?(object)
91
+ YARD::CodeObjects::Lucid.constants.any? { |constant| object.class.name == "YARD::CodeObjects::Lucid::#{constant}" }
92
+ end
93
+
94
+ # The re-write rules will only change the nav link to a new menu if it is a
95
+ # a Lucid CodeObject that we care about and that we have also generated a
96
+ # menu for that item.
97
+ def rewrite_nav_url(nav_url)
98
+ if object.is_a?(YARD::CodeObjects::Lucid::Feature) && current_menu_lists.include?('features')
99
+ nav_url.gsub('class_list.html','feature_list.html')
100
+ elsif object.is_a?(YARD::CodeObjects::Lucid::FeatureDirectory) && current_menu_lists.include?('directories')
101
+ nav_url.gsub('class_list.html','featuredirectories_list.html')
102
+ elsif object.is_a?(YARD::CodeObjects::Lucid::Tag) && current_menu_lists.include?('tags')
103
+ nav_url.gsub('class_list.html','tag_list.html')
104
+ elsif object.is_a?(YARD::CodeObjects::Lucid::Step) && current_menu_lists.include?('steps')
105
+ nav_url.gsub('class_list.html','step_list.html')
106
+ elsif object.is_a?(YARD::CodeObjects::Lucid::StepTransformersObject) && current_menu_lists.include?('step definitions')
107
+ nav_url.gsub('class_list.html','stepdefinition_list.html')
108
+ else
109
+ nav_url
110
+ end
111
+ end
@@ -0,0 +1,26 @@
1
+ <% if @elements && !@elements.empty? %>
2
+ <% i = (@elements.length % 2 == 0 ? 1 : 0) %>
3
+ <table style="margin-left: 10px; width: 100%;">
4
+ <tr>
5
+ <td valign='top' width="50%">
6
+ <% @elements.each do |letter, objects| %>
7
+ <% if (i += 1) > (@elements.length / 2 + 1) %>
8
+ </td><td valign='top' width="50%">
9
+ <% i = 0 %>
10
+ <% end %>
11
+ <ul id="alpha_<%= letter %>" class="alpha">
12
+ <li class="letter"><%= letter %></li>
13
+ <ul>
14
+ <% objects.each do |obj| %>
15
+ <li>
16
+ <%= linkify obj, obj.value %>
17
+ <small>(<%= obj.file %>)</small>
18
+ </li>
19
+ <% end %>
20
+ </ul>
21
+ </ul>
22
+ <% end %>
23
+ </td>
24
+ </tr>
25
+ </table>
26
+ <% end %>
@@ -0,0 +1,49 @@
1
+ def init
2
+ super
3
+ sections.push :specifications
4
+ @namespace = object
5
+ end
6
+
7
+ def features
8
+ @features ||= Registry.all(:feature)
9
+ end
10
+
11
+ def tags
12
+ @tags ||= Registry.all(:tag).sort_by { |l| l.value.to_s }
13
+ end
14
+
15
+ def feature_directories
16
+ @feature_directories ||= YARD::CodeObjects::Lucid::LUCID_NAMESPACE.children.find_all { |child| child.is_a?(YARD::CodeObjects::Lucid::FeatureDirectory) }
17
+ end
18
+
19
+ def feature_subdirectories
20
+ @feature_subdirectories ||= Registry.all(:featuredirectory) - feature_directories
21
+ end
22
+
23
+ def step_transformers
24
+ YARD::CodeObjects::Lucid::LUCID_STEPTRANSFORM_NAMESPACE
25
+ end
26
+
27
+ def step_definitions
28
+ @step_definitions ||= YARD::Registry.all(:stepdefinition)
29
+ end
30
+
31
+ def transformers
32
+ @transformers ||= YARD::Registry.all(:steptransform)
33
+ end
34
+
35
+ def undefined_steps
36
+ @undefined_steps ||= Registry.all(:step).reject { |s| s.definition || s.scenario.outline? }
37
+ end
38
+
39
+ def alpha_table(objects)
40
+ @elements = Hash.new
41
+
42
+ objects = run_verifier(objects)
43
+ objects.each { |o| (@elements[o.value.to_s[0,1].upcase] ||= []) << o }
44
+ @elements.values.each { |v| v.sort! {|a,b| b.value.to_s <=> a.value.to_s } }
45
+ @elements = @elements.sort_by { |l,o| l.to_s }
46
+
47
+ @elements.each { |letter,objects| objects.sort! {|a,b| b.value.to_s <=> a.value.to_s } }
48
+ erb(:alpha_table)
49
+ end
@@ -0,0 +1,46 @@
1
+ <% if @namespace %>
2
+ <div id="lucid_logo">&nbsp;</div>
3
+ <div id="lucid_links">
4
+ <a href="https://github.com/jeffnyman/yard-lucid">Yard-Lucid</a> |
5
+ <a href="http://github.com/cucumber/cucumber/wiki/Gherkin">Gherkin</a> |
6
+ <a href="http://cukes.info/">Cucumber</a> |
7
+ <a href="http://yardoc.org/">YARD</a>
8
+ </div>
9
+
10
+ <div class="specifications">
11
+ <% if features && !features.empty? %>
12
+ <%= alpha_table(features) %>
13
+ <% else %>
14
+ <!-- No Features Defined -->
15
+ <div class="none">No Features Defined</div>
16
+ <% end %>
17
+
18
+ <div id="directory" style="margin-left: 40px;">
19
+ <div class="title"><span class="name">Tags</span></div>
20
+ </div>
21
+ <div class="tags">
22
+ <%= tags.collect {|tag| linkify(tag,tag.value) }.join(",\n") %>
23
+ </div>
24
+
25
+ <% if feature_subdirectories && !feature_subdirectories.empty? %>
26
+ <div id="directory" style="margin-left: 40px;">
27
+ <div class="title"><span class="name">Subdirectories</span></div>
28
+ </div>
29
+ <%= alpha_table(feature_subdirectories) %>
30
+ <% else %>
31
+ <!-- No Feature Directories -->
32
+ <% end %>
33
+
34
+ <div id="directory" style="margin-left: 40px;">
35
+ <div class="title"><span class="name">Step Definitions &amp; Transforms</span></div>
36
+ </div>
37
+ <div class="steptransformers">
38
+ <%= step_definitions.length %>
39
+ <a href="<%= url_for step_transformers, "step_definitions" %>">Step Definitions</a>
40
+ <%= transformers.length %>
41
+ <a href="<%= url_for step_transformers, "step_transforms" %>">Transforms</a>
42
+ and <%= undefined_steps.length %>
43
+ <a href="<%= url_for step_transformers, "undefined_steps" %>">Undefined Steps</a>
44
+ </div>
45
+ </div>
46
+ <% end %>
@@ -0,0 +1,12 @@
1
+ <div class="title">
2
+ <% if @item_type %>
3
+ <a class="control" id="<%= @item_type.gsub(/\s/,'') %>">[Collapse All]</a>
4
+ <div style="clear: right;"></div>
5
+ <% end %>
6
+
7
+ <% if @item_anchor_name %>
8
+ <a name="<%= @item_anchor_name %>">
9
+ <% end %>
10
+ <div class="name"><%= @item_title %></div>
11
+ </div>
12
+
@@ -0,0 +1,9 @@
1
+ <div class="specifications">
2
+ <div class="title">Step Definitions &amp; Transforms</div>
3
+
4
+ <div class="summary">
5
+ <div><%= step_definitions.length %><a href="#step_definitions">Step Definitions</a></div>
6
+ <div><%= step_transforms.length %><a href="#step_transforms">Step Transforms</a></div>
7
+ <div><%= undefined_steps.length %><a href="#undefined_steps">Undefined Steps</a></div>
8
+ </div>
9
+ </div>
@@ -0,0 +1,92 @@
1
+ def init
2
+ super
3
+ sections.push :index, :stepdefinitions, :steptransforms, :undefinedsteps
4
+ end
5
+
6
+ def step_definitions
7
+ @step_definitions ||= begin
8
+ YARD::Registry.all(:stepdefinition).sort_by { |definition| definition.steps.length * -1 }
9
+ end
10
+ end
11
+
12
+ def step_transforms
13
+ @step_transforms ||= begin
14
+ YARD::Registry.all(:steptransform).sort_by { |definition| definition.steps.length * -1 }
15
+ end
16
+ end
17
+
18
+ def undefined_steps
19
+ @undefined_steps ||= begin
20
+ unique_steps(Registry.all(:step).reject { |s| s.definition || s.scenario.outline? }).sort_by{|steps| steps.last.length * -1 }
21
+ end
22
+ end
23
+
24
+ def stepdefinitions
25
+ @item_title = "Step Definitions"
26
+ @item_anchor_name = "step_definitions"
27
+ @item_type = "step definition"
28
+ @items = step_definitions
29
+ erb(:header) + erb(:transformers)
30
+ end
31
+
32
+ def steptransforms
33
+ @item_title = "Step Transforms"
34
+ @item_anchor_name = "step_transforms"
35
+ @item_type = "step transform"
36
+ @items = step_transforms
37
+ erb(:header) + erb(:transformers)
38
+ end
39
+
40
+ def undefinedsteps
41
+ @item_title = "Undefined Steps"
42
+ @item_anchor_name = "undefined_steps"
43
+ @item_type = nil
44
+ @items = undefined_steps
45
+ erb(:header) + erb(:undefinedsteps)
46
+ end
47
+
48
+
49
+ def unique_steps(steps)
50
+ uniq_steps = {}
51
+ steps.each {|s| (uniq_steps[s.value.to_s] ||= []) << s }
52
+ uniq_steps
53
+ end
54
+
55
+ def display_comments_for(item)
56
+ begin
57
+ T('docstring').run(options.dup.merge({:object => item}))
58
+ rescue
59
+ log.warn %{An error occurred while attempting to render the comments for: #{item.location} }
60
+ return ""
61
+ end
62
+ end
63
+
64
+ def link_constants(definition)
65
+ value = definition.literal_value.dup
66
+
67
+ definition.constants_from_value(value).each do |name|
68
+ constant = YARD::Registry.all(:constant).find{|c| c.name == name.to_sym }
69
+ value.gsub!(/\b#{name}\b/,"<a href='#{url_for(constant)}'>#{name}</a>") if constant
70
+ end
71
+
72
+ value
73
+ end
74
+
75
+ def link_transformed_step(step)
76
+ value = step.value.dup
77
+
78
+ if step.definition
79
+ matches = step.value.match(step.definition.regex)
80
+
81
+ if matches
82
+ matches[1..-1].reverse.each_with_index do |match,index|
83
+ next if match == nil
84
+ transform = step.transforms.find {|transform| transform.regex.match(match) }
85
+
86
+ value[matches.begin((matches.size - 1) - index)..(matches.end((matches.size - 1) - index) - 1)] = transform ? "<a href='#{url_for(transform)}'>#{h(match)}</a>" : "<span class='match'>#{match}</span>"
87
+ end
88
+ end
89
+ end
90
+
91
+ value
92
+ end
@@ -0,0 +1,74 @@
1
+ <% @items.each do |item| %>
2
+ <div class="transformer <%= @item_type.gsub(/\s/,'') %>
3
+ <%= "nodefinitions" if item.steps.nil? || item.steps.empty? %>
4
+ <%= "pending" if item.pending %>">
5
+ <a name="<%= anchor_for item %>"></a>
6
+ <div class="title">
7
+ <span class="pre"><%= h item.keyword %></span>
8
+ <span class="name"><%= item.value %></span>
9
+ <div style="float: right;">
10
+ <a href="http://rubular.com/?regex=<%= urlencode item.value %>" target="_blank">Rubular</a>
11
+ <%= "| PENDING" if item.pending %>
12
+ <%= "| UNUSED" if item.steps.nil? || item.steps.empty? %>
13
+ <a class="stepdef" href="#">[Collapse]</a>
14
+ </div>
15
+ <div style="clear: both;"></div>
16
+ </div>
17
+
18
+ <div class="details">
19
+ <div class="meta" style="clear: right;">
20
+ <div class="file"><%= h item.location %></div>
21
+ </div>
22
+
23
+ <!-- Comments -->
24
+ <div>
25
+ <%= display_comments_for item %>
26
+ </div>
27
+
28
+ <!-- Source Code -->
29
+ <div class="method_details_list">
30
+ <table class="source_code">
31
+ <tr>
32
+ <td>
33
+ <pre class="lines"><%= "" %><%= h format_lines(item) %></pre>
34
+ </td>
35
+ <td>
36
+ <pre class="code"><%= "" %><%= html_syntax_highlight item.source %></pre>
37
+ </td>
38
+ </tr>
39
+ </table>
40
+ </div>
41
+
42
+ <!-- Matching Step Instances -->
43
+ <% if item.steps.length > 0 %>
44
+ <div class='showSteps'>
45
+ [<a href='#' class='toggleSteps' alt="<%= item.steps.length %> steps">Hide <%= item.steps.length %> steps</a>]
46
+ </div>
47
+ <% end %>
48
+ <div class="steps">
49
+ <% if item.steps && !item.steps.empty? %>
50
+ <% unique_steps(item.steps).each_with_index do |uniq_step,step_index| %>
51
+ <div class="step <%= (step_index + 1) % 2 == 0 ? 'even' : 'odd' %>">
52
+ <div>
53
+ <span class="predicate">
54
+ <%= h uniq_step.last.first.keyword %>
55
+ </span>
56
+ <span class="defined">
57
+ <%= link_transformed_step(uniq_step.last.first) %>
58
+ </span>
59
+ </div>
60
+ <% uniq_step.last.each do |step| %>
61
+ <a class="definition" style="clear: right;" href="<%= url_for step.scenario.feature %>"><%= h step.location %></a>
62
+ <% end %>
63
+ <div style="clear: both;"></div>
64
+ </div>
65
+ <% end %>
66
+ <% else %>
67
+ <div class="undefined">No steps were found to match this <%= @item_type %>.</div>
68
+ <% end%>
69
+ </div>
70
+ </div>
71
+
72
+ <div style="margin: 30px 20px; border-top: 1px dotted #AAA;"></div>
73
+ </div>
74
+ <% end %>
@@ -0,0 +1,26 @@
1
+ <div class="transformer">
2
+ <div class="steps">
3
+ <% if @undefined_steps && !@undefined_steps.empty? %>
4
+ <% @undefined_steps.each_with_index do |uniq_step,step_index| %>
5
+ <div class="step <%= (step_index + 1) % 2 == 0 ? 'even' : 'odd' %>">
6
+ <div>
7
+ <span class="predicate"><%= uniq_step.last.first.keyword %></span>
8
+ <span class="undefined">
9
+ <%= h uniq_step.last.first.value %>
10
+ </span>
11
+ </div>
12
+ <% uniq_step.last.each do |step| %>
13
+ <a class="definition" style="clear: right;" href="<%= url_for step.scenario.feature %>">
14
+ <%= h step.location %>
15
+ </a>
16
+ <% end%>
17
+ <div style="clear: both;"></div>
18
+ </div>
19
+ <% end %>
20
+ <% else %>
21
+ <div class="steps">
22
+ <div class="undefined">No undefined steps</div>
23
+ </div>
24
+ <% end%>
25
+ </div>
26
+ </div>
@@ -0,0 +1,32 @@
1
+ <% if @elements && !@elements.empty? %>
2
+ <% i = (@elements.length % 2 == 0 ? 1 : 0) %>
3
+ <table style="margin-left: 10px; width: 100%;">
4
+ <tr>
5
+ <td valign='top' width="50%">
6
+ <% @elements.each do |letter, objects| %>
7
+ <% if (i += 1) > (@elements.length / 2 + 1) %>
8
+ </td><td valign='top' width="50%">
9
+ <% i = 0 %>
10
+ <% end %>
11
+ <ul id="alpha_<%= letter %>" class="alpha">
12
+ <li class="letter"><%= letter %></li>
13
+ <ul>
14
+ <% objects.each do |obj| %>
15
+ <li>
16
+ <% if obj.is_a?(YARD::CodeObjects::Lucid::Scenario) || obj.is_a?(YARD::CodeObjects::Lucid::ScenarioOutline) %>
17
+ <a href="<%= url_for(obj.feature,"scenario_#{obj.path[(/.+_(\d+)$/),1]}") %>">
18
+ <%= h obj.value %>
19
+ </a>
20
+ <% else %>
21
+ <%= linkify obj, obj.value %>
22
+ <% end %>
23
+ <small>(<%= obj.file %>)</small>
24
+ </li>
25
+ <% end %>
26
+ </ul>
27
+ </ul>
28
+ <% end %>
29
+ </td>
30
+ </tr>
31
+ </table>
32
+ <% end %>
@@ -0,0 +1,26 @@
1
+ def init
2
+ super
3
+ @tag = object
4
+
5
+ sections.push :tag
6
+ end
7
+
8
+ def features
9
+ @tag.features
10
+ end
11
+
12
+ def scenarios
13
+ @tag.scenarios
14
+ end
15
+
16
+ def alpha_table(objects)
17
+ @elements = Hash.new
18
+
19
+ objects = run_verifier(objects)
20
+ objects.each { |o| (@elements[o.value.to_s[0,1].upcase] ||= []) << o }
21
+ @elements.values.each { |v| v.sort! {|a,b| b.value.to_s <=> a.value.to_s } }
22
+ @elements = @elements.sort_by {|l,o| l.to_s }
23
+
24
+ @elements.each { |letter,objects| objects.sort! { |a,b| b.value.to_s <=> a.value.to_s } }
25
+ erb(:alpha_table)
26
+ end
@@ -0,0 +1,31 @@
1
+ <div class="tag">
2
+ <div class="title">
3
+ <span class="pre">Tag:</span>
4
+ <span class="name"><%= @tag.value %></span>
5
+ </div>
6
+
7
+ <div class="meta">
8
+ <div class="file">
9
+ <%= @tag.features.size > 0 ? "#{@tag.features.size} feature#{@tag.features.size > 1 ? 's' : ''} (with #{@tag.indirect_scenarios.size} scenario#{@tag.indirect_scenarios.size > 1 ? 's' : ''})" : "" %>
10
+ <%= " and " if @tag.features.size > 0 && @tag.scenarios.size > 0 %>
11
+ <%= @tag.scenarios.size > 0 ? "#{@tag.scenarios.size} scenario#{@tag.scenarios.size > 1 ? 's' : ''}" : "" %>
12
+ </div>
13
+ </div>
14
+
15
+ <div style="margin-top: 20px;">&nbsp;</div>
16
+
17
+ <% if features && !features.empty? %>
18
+ <div id="features" style="margin-left: 40px;">
19
+ <div class="title"><span class="name">Features</span></div>
20
+ </div>
21
+ <%= alpha_table(features) %>
22
+
23
+ <% end %>
24
+
25
+ <% if scenarios && !scenarios.empty? %>
26
+ <div id="features" style="margin-left: 40px;">
27
+ <div class="title"><span class="name">Scenarios</span></div>
28
+ </div>
29
+ <%= alpha_table(scenarios) %>
30
+ <% end %>
31
+ </div>
@@ -0,0 +1,23 @@
1
+ module YARD::CodeObjects::Lucid
2
+ module LocationHelper
3
+ def line_number
4
+ files.first.last
5
+ end
6
+
7
+ def file
8
+ files.first.first if files && !files.empty?
9
+ end
10
+
11
+ def location
12
+ "#{file}:#{line_number}"
13
+ end
14
+ end
15
+
16
+ class Base < YARD::CodeObjects::Base
17
+ include LocationHelper
18
+
19
+ def path
20
+ @value || super
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,12 @@
1
+ module YARD::CodeObjects::Lucid
2
+ class Feature < NamespaceObject
3
+ attr_accessor :background, :comments, :description, :keyword, :scenarios, :tags, :value
4
+
5
+ def initialize(namespace,name)
6
+ @comments = ""
7
+ @scenarios = []
8
+ @tags = []
9
+ super(namespace,name.to_s.strip)
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,43 @@
1
+ module YARD::CodeObjects::Lucid
2
+
3
+ class NamespaceObject < YARD::CodeObjects::NamespaceObject
4
+ include LocationHelper
5
+ def value ; nil ; end
6
+ end
7
+
8
+ class Specifications < NamespaceObject ; end
9
+ class FeatureTags < NamespaceObject ; end
10
+ class StepTransformersObject < NamespaceObject ; end
11
+
12
+ class FeatureDirectory < YARD::CodeObjects::NamespaceObject
13
+ attr_accessor :description
14
+
15
+ def initialize(namespace,name)
16
+ super(namespace,name)
17
+ @description = ""
18
+ end
19
+
20
+ def location
21
+ files.first.first if files && !files.empty?
22
+ end
23
+
24
+ def expanded_path
25
+ to_s.split('::')[1..-1].join('/')
26
+ end
27
+
28
+ def value ; name ; end
29
+
30
+ def features
31
+ children.find_all { |d| d.is_a?(Feature) }
32
+ end
33
+
34
+ def subdirectories
35
+ subdirectories = children.find_all { |d| d.is_a?(FeatureDirectory) }
36
+ subdirectories + subdirectories.collect { |s| s.subdirectories }.flatten
37
+ end
38
+ end
39
+
40
+ LUCID_NAMESPACE = Specifications.new(:root, "specifications") unless defined?(LUCID_NAMESPACE)
41
+ LUCID_TAG_NAMESPACE = FeatureTags.new(LUCID_NAMESPACE, "tags") unless defined?(LUCID_TAG_NAMESPACE)
42
+ LUCID_STEPTRANSFORM_NAMESPACE = StepTransformersObject.new(LUCID_NAMESPACE, "step_transformers") unless defined?(LUCID_STEPTRANSFORM_NAMESPACE)
43
+ end
@@ -0,0 +1,20 @@
1
+ module YARD::CodeObjects::Lucid
2
+ class Scenario < NamespaceObject
3
+ attr_accessor :value, :comments, :keyword, :description, :steps, :tags, :feature
4
+
5
+ def initialize(namespace,name)
6
+ super(namespace,name.to_s.strip)
7
+ @comments = @description = @keyword = @value = @feature = nil
8
+ @steps = []
9
+ @tags = []
10
+ end
11
+
12
+ def background?
13
+ @keyword == "Background"
14
+ end
15
+
16
+ def outline?
17
+ false
18
+ end
19
+ end
20
+ end