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,27 @@
1
+ <% @row = @row == 'even' ? 'odd' : 'even' %>
2
+ <% if @directory.children %>
3
+ <ul>
4
+ <% @directory.children.sort { |x,y| x.value.to_s <=> y.value.to_s }.each_with_index do |child, index| %>
5
+ <% if child.is_a?(YARD::CodeObjects::Lucid::Feature) %>
6
+ <li class="<%= @row %>">
7
+ <div class="item" style="padding-left: <%= @padding %>px">
8
+ <%= linkify child, child.value %>
9
+ <small><%= child.location %></small>
10
+ </div>
11
+ </li>
12
+ <% @row = @row == 'even' ? 'odd' : 'even' %>
13
+ <% end %>
14
+
15
+ <% if child.is_a?(YARD::CodeObjects::Lucid::FeatureDirectory) %>
16
+ <li class="<%= @row %>">
17
+ <div class="item" style="padding-left: <%= @padding %>px">
18
+ <%= "<a class='toggle'></a>" unless child.features.empty? && child.subdirectories.empty? %>
19
+ <%= linkify child, child.value.to_s.capitalize %>
20
+ <small><%= child.location %></small>
21
+ </div>
22
+ <%= directory_node child, @padding + 15, @row %>
23
+ </li>
24
+ <% end %>
25
+ <% end %>
26
+ </ul>
27
+ <% end %>
@@ -0,0 +1,11 @@
1
+ <% n = 'odd' %>
2
+ <% @items.each do |directory| %>
3
+ <li class="<%= n %>">
4
+ <div class="item" style="padding-left: 30px">
5
+ <%= "<a class='toggle'></a>" unless directory.features.empty? && directory.subdirectories.empty? %>
6
+ <%= linkify directory, directory.value %>
7
+ <small><%= directory.location %></small>
8
+ </div>
9
+ <%= directory_node directory, 45, n %>
10
+ </li>
11
+ <% end %>
@@ -0,0 +1,36 @@
1
+ <% n = 'odd' %>
2
+ <li class="<%= n %>">
3
+ <div class="item" style="padding-left: 30px">
4
+ <%= all_features_link %>
5
+ </div>
6
+ </li>
7
+ <% n = n == 'odd' ? 'even' : 'odd' %>
8
+ <% @items.each do |feature| %>
9
+ <li class="<%= n %>">
10
+ <div class="item" style="padding-left: 30px">
11
+ <%= "<a class='toggle'></a>" unless feature.scenarios.empty? %>
12
+ <%= linkify feature, feature.value %>
13
+ <small><%= feature.location %></small>
14
+ </div>
15
+
16
+ <% n = n == 'odd' ? 'even' : 'odd' %>
17
+ <% if feature.scenarios %>
18
+ <ul>
19
+ <% feature.scenarios.each_with_index do |scenario,index| %>
20
+ <li class="<%= n %>">
21
+ <div class="item" style="padding-left: 45px">
22
+ <span class='object_link'>
23
+ <a href="<%= url_for(scenario.feature,"scenario_#{index}") %>"
24
+ title="<%= h scenario.value %>">
25
+ <%= h scenario.value %>
26
+ </a>
27
+ </span>
28
+ <small><%= scenario.location %></small>
29
+ </div>
30
+ </li>
31
+ <% n = n == 'odd' ? 'even' : 'odd' %>
32
+ <% end %>
33
+ </ul>
34
+ <% end %>
35
+ </li>
36
+ <% end %>
@@ -0,0 +1,20 @@
1
+ <li>
2
+ <div class="item" style="padding-left: 30px">
3
+ <%= linkify YARD::CodeObjects::Lucid::LUCID_STEPTRANSFORM_NAMESPACE, "All Step Definitions" %>
4
+ </div>
5
+ </li>
6
+ <% n = 'odd' %>
7
+ <% @items.each do |stepdef| %>
8
+ <li class="<%= n %>">
9
+ <div class="item" style="padding-left: 30px">
10
+ <span class='object_link'>
11
+ <span class="pre"><%= stepdef.keyword %></span>
12
+ <a href="<%= url_for stepdef %>" title="<%= h stepdef.value %>">
13
+ <span class="name"><%= h stepdef.literal_value %></span>
14
+ </a>&nbsp;&nbsp;
15
+ </span>
16
+ <small><%= h(stepdef.location) %></small>
17
+ </div>
18
+ </li>
19
+ <% n = n == 'even' ? 'odd' : 'even' %>
20
+ <% end %>
@@ -0,0 +1,20 @@
1
+ <li class='odd'>
2
+ <div class="item" style="padding-left: 30px">
3
+ <%= linkify YARD::CodeObjects::Lucid::LUCID_STEPTRANSFORM_NAMESPACE, "All Defined Steps" %>
4
+ </div>
5
+ </li>
6
+ <% n = 'even' %>
7
+ <% @items.each do |step| %>
8
+ <li class="<%= n %>">
9
+ <div class="item" style="padding-left: 30px">
10
+ <span class='object_link'>
11
+ <a href="<%= url_for step.scenario.feature %>" title="<%= h step.value %>">
12
+ <span class="pre"><%= step.keyword %></span>
13
+ <span class="name"><%= h(step.value) %></span>
14
+ </a>
15
+ </span>
16
+ <span class="">(<%= h(step.file) %>)<span>
17
+ </div>
18
+ </li>
19
+ <% n = n == 'even' ? 'odd' : 'even' %>
20
+ <% end %>
@@ -0,0 +1,16 @@
1
+ <li>
2
+ <div class="item" style="padding-left: 30px;">
3
+ <%= linkify YARD::CodeObjects::Lucid::LUCID_TAG_NAMESPACE, "All Tags" %>
4
+ </div
5
+ </li>
6
+
7
+ <% n = 'odd' %>
8
+ <% @items.each do |tag| %>
9
+ <li class="<%= n %>">
10
+ <div class="item" style="padding-left: 30px;">
11
+ <%= linkify tag, tag.value %>
12
+ <small style="display: inline;"><%= tag.all_scenarios.size %></small>
13
+ </div>
14
+ </li>
15
+ <% n = n == 'odd' ? 'even' : 'odd' %>
16
+ <% end %>
@@ -0,0 +1,284 @@
1
+ function lucidKeyboardShortcuts() {
2
+ if (window.top.frames.main) return;
3
+ $(document).keypress(function(evt) {
4
+ if (evt.altKey || evt.ctrlKey || evt.metaKey || evt.shiftKey) return;
5
+ if (typeof evt.target !== "undefined" &&
6
+ (evt.target.nodeName == "INPUT" ||
7
+ evt.target.nodeName == "TEXTAREA")) return;
8
+ switch (evt.charCode) {
9
+ case 68: case 100: $('#stepdefinition_list_link').click(); break; // 'd'
10
+ case 82: case 114: $('#feature_list_link').click(); break; // 'r'
11
+ case 83: case 115: $('#step_list_link').click(); break; // 's'
12
+ case 84: case 116: $('#tag_list_link').click(); break; // 't'
13
+ }
14
+ });
15
+ }
16
+
17
+ $(lucidKeyboardShortcuts);
18
+
19
+ $(function() {
20
+ // Feature Page - Scenarios
21
+ $('.scenario div.title').click(function(eventObject) {
22
+ if (typeof eventObject.currentTarget !== "undefined") {
23
+ toggleScenario( $($(eventObject.currentTarget).parent()) );
24
+ }
25
+ });
26
+
27
+ // Developer View
28
+ // Click + Developer View = toggle the expansion of all tags, location, and comments
29
+ $('#view').click(function(eventObject) {
30
+ if (typeof eventObject.currentTarget !== "undefined") {
31
+ var view = eventObject.currentTarget;
32
+
33
+ if (view.innerHTML === '[More Detail]') {
34
+ $('.developer').show(500);
35
+ view.innerHTML = '[Less Detail]';
36
+ } else {
37
+ $('.developer').hide(500);
38
+ // Already hidden elements with .developer sub-elements were not getting message
39
+ $('.developer').each(function() {
40
+ $(this).css('display','none');
41
+ });
42
+ view.innerHTML = '[More Detail]';
43
+ }
44
+ }
45
+ });
46
+
47
+ // Expand/Collapse All
48
+ $('#expand').click(function(eventObject) {
49
+
50
+ if (typeof eventObject.currentTarget !== "undefined") {
51
+ if (eventObject.currentTarget.innerHTML === '[Expand All]') {
52
+ eventObject.currentTarget.innerHTML = '[Collapse All]';
53
+ $('div.scenario > div.details:hidden').each(function() {
54
+ toggleScenario( $($(this).parent()) );
55
+ });
56
+ } else {
57
+ eventObject.currentTarget.innerHTML = '[Expand All]';
58
+ $('div.scenario > div.details:visible').each(function() {
59
+ toggleScenario( $($(this).parent()) );
60
+ });
61
+ }
62
+ }
63
+ });
64
+
65
+ // Expand/Collapse All
66
+ $('#stepdefinition,#steptransform').click(function(eventObject) {
67
+
68
+ if (typeof eventObject.currentTarget !== "undefined") {
69
+ if (eventObject.currentTarget.innerHTML === '[Expand All]') {
70
+ eventObject.currentTarget.innerHTML = '[Collapse All]';
71
+ $('div.' + eventObject.currentTarget.id + ' > div.details:hidden').each(function() {
72
+ $(this).show(200);
73
+ });
74
+ $('div.' + eventObject.currentTarget.id + ' a.stepdef').text("[Collapse]")
75
+ } else {
76
+ eventObject.currentTarget.innerHTML = '[Expand All]';
77
+ $('div.' + eventObject.currentTarget.id + ' > div.details:visible').each(function() {
78
+ $(this).hide(200);
79
+ });
80
+ console.log(eventObject.currentTarget.id);
81
+ $('div.' + eventObject.currentTarget.id + ' a.stepdef').text('[Expand]');
82
+ }
83
+ }
84
+ });
85
+
86
+ $('.stepdef').click(function(eventObject) {
87
+ if (typeof eventObject.currentTarget !== "undefined") {
88
+ if (eventObject.currentTarget.innerHTML === '[Expand]') {
89
+ eventObject.currentTarget.innerHTML = '[Collapse]';
90
+ $(eventObject.target).parent().parent().parent().find("div.details:hidden").each(function() {
91
+ $(this).show(200);
92
+ });
93
+ } else {
94
+ eventObject.currentTarget.innerHTML = '[Expand]';
95
+ $(eventObject.target).parent().parent().parent().find("div.details:visible").each(function() {
96
+ $(this).hide(200);
97
+ });
98
+ }
99
+ }
100
+ });
101
+
102
+
103
+ // Scenario Outlines - Toggle Examples
104
+ $('.outline table tr').click(function(eventObject) {
105
+ if (typeof eventObject.currentTarget !== "undefined") {
106
+ var exampleRow = $(eventObject.currentTarget);
107
+
108
+ if (eventObject.currentTarget.className.match(/example\d+-\d+/) == null) {
109
+ return false;
110
+ }
111
+
112
+ var exampleClass = eventObject.currentTarget.className.match(/example\d+-\d+/)[0];
113
+ var example = exampleRow.closest('div.details').find('.' + exampleClass);
114
+
115
+ var currentExample = null;
116
+
117
+ $('.outline table tr').each(function() {
118
+ $(this).removeClass('selected');
119
+ });
120
+
121
+ if ( example[0].style.display == 'none' ) {
122
+ currentExample = example[0];
123
+ exampleRow.addClass('selected');
124
+ } else {
125
+ currentExample = exampleRow.closest('div.details').find('.steps')[0];
126
+ }
127
+
128
+ // hide everything
129
+ exampleRow.closest('div.details').find('.steps').each(function() {
130
+ $(this).hide();
131
+ });
132
+
133
+ // show the selected
134
+ $(currentExample).show();
135
+ }
136
+ });
137
+ });
138
+
139
+
140
+ function toggleScenario(scenario) {
141
+ var state = scenario.find(".attributes input[name='collapsed']")[0];
142
+
143
+ if (state.value === 'true') {
144
+ scenario.find("div.details").each(function() {
145
+ $(this).show(500);
146
+ });
147
+ state.value = "false";
148
+ scenario.find('a.toggle').each(function() {
149
+ this.innerHTML = ' - ';
150
+ });
151
+
152
+ } else {
153
+ scenario.find("div.details").each(function() {
154
+ $(this).hide(500);
155
+ });
156
+ state.value = "true";
157
+ scenario.find('a.toggle').each(function() {
158
+ this.innerHTML = ' + ';
159
+ });
160
+ }
161
+ }
162
+
163
+ function updateTagFiltering(tagString) {
164
+ var formulaTags = determineTagsUsedInFormula(tagString);
165
+ displayExampleCommandLine(formulaTags);
166
+ displayQualifyingFeaturesAndScenarios(formulaTags);
167
+ fixSectionRowAlternations();
168
+ }
169
+
170
+ function clearTagFiltering() {
171
+ updateTagFiltering("");
172
+ }
173
+
174
+ function determineTagsUsedInFormula(tagString) {
175
+ tagString = tagString.replace(/^(\s+)|(\s+)$/,'').replace(/\s{2,}/,' ');
176
+
177
+ var tagGroup = tagString.match(/(?:~)?@\w+(,(?:~)?@\w+)*/g);
178
+ var returnTags = [];
179
+
180
+ if (tagGroup) {
181
+ tagGroup.forEach(function(tag, index, array) {
182
+ console.log("Tag Group: " + tag);
183
+ var validTags = removeInvalidTags(tag)
184
+ if (validTags != "") {
185
+ returnTags.push(validTags);
186
+ }
187
+ });
188
+ }
189
+
190
+ return returnTags;
191
+ }
192
+
193
+ function removeInvalidTags(tagGroup) {
194
+ tagGroup.split(",").forEach(function(tag, index, array) {
195
+ baseTag = tag.match(/^~(.+)/) ? tag.match(/^~(.+)/)[1] : tag;
196
+
197
+ if (tag_list.indexOf(baseTag) === -1) {
198
+ tagGroup = tagGroup.replace(new RegExp(',?' + tag + ',?'),"")
199
+ }
200
+ });
201
+
202
+ return tagGroup;
203
+ }
204
+
205
+ function displayExampleCommandLine(tags) {
206
+ $("#command_example")[0].innerHTML = "cucumber ";
207
+
208
+ if (tags.length > 0) {
209
+ $("#command_example")[0].innerHTML += "--tags " + tags.join(" --tags ");
210
+ }
211
+ }
212
+
213
+ function fixSectionRowAlternations() {
214
+ $(".feature:visible,.scenario:visible").each(function(index){
215
+ $(this).removeClass("odd even").addClass( ((index + 1) % 2 == 0 ? "even" : "odd") );
216
+ });
217
+ }
218
+
219
+ function displayQualifyingFeaturesAndScenarios(tags) {
220
+ if (tags.length > 0) {
221
+ $(".feature,.scenario").each(function(feature){
222
+ $(this).hide();
223
+ });
224
+
225
+ var tagSelectors = generateCssSelectorFromTags(tags);
226
+
227
+ tagSelectors.forEach(function(selector,selectorIndex,selectorArray) {
228
+ var tags = selector;
229
+
230
+ $(".feature." + tags).each(function(index) {
231
+ $(this).show();
232
+ });
233
+ $(".scenario." + tags).each(function(index) {
234
+ $(this).show();
235
+ $(this).parent().prev().show();
236
+ });
237
+ });
238
+
239
+ if ( $(".feature:visible,.scenario:visible").length == 0 ) {
240
+ $("#features div.undefined").show();
241
+ } else {
242
+ $("#features div.undefined").hide();
243
+ }
244
+ } else {
245
+ $(".feature:hidden,.scenario:hidden").each(function(feature){
246
+ $(this).show();
247
+ });
248
+ }
249
+ }
250
+
251
+ function generateCssSelectorFromTags(tagGroups) {
252
+ var tagSelectors = [ "" ];
253
+
254
+ tagGroups.forEach(function(tagGroup,index,array) {
255
+ var newTagSelectors = [];
256
+
257
+ tagSelectors.forEach(function(selector,selectorIndex,selectorArray) {
258
+ tagGroup.split(",").forEach(function(tag,tagIndex,tagArray) {
259
+ if ( tag.match(/^~@.+$/) ) {
260
+ tag = tag.match(/^~(@.+)$/)[1]
261
+ newTagSelectors.push((selector + ":not(." + tag.replace(/@/g,"\\@") +")").trim());
262
+ } else {
263
+ newTagSelectors.push((selector + "." + tag.replace(/@/g,"\\@")).trim());
264
+ }
265
+ });
266
+ });
267
+ tagSelectors = newTagSelectors;
268
+ });
269
+ return tagSelectors;
270
+ }
271
+
272
+
273
+ function createStepDefinitionLinks() {
274
+ $('.toggleSteps').toggle(function() {
275
+ $(this).parent().next().slideUp(100);
276
+ $(this).text("View " + $(this).attr('alt'));
277
+ },
278
+ function() {
279
+ $(this).parent().next().slideDown(100);
280
+ $(this).text("Hide " + $(this).attr('alt'));
281
+ });
282
+ }
283
+
284
+ $(createStepDefinitionLinks);
@@ -0,0 +1,199 @@
1
+ include YARD::Templates::Helpers::HtmlHelper
2
+
3
+ def init
4
+ super
5
+
6
+ # Additional javascript that power the additional menus, collapsing, etc.
7
+ asset "js/lucid.js", file("js/lucid.js",true)
8
+
9
+ serialize_object_type :feature
10
+
11
+ serialize_object_type :tag
12
+
13
+ # Generates the specifications splash page with the 'specifications' template
14
+ serialize(YARD::CodeObjects::Lucid::LUCID_NAMESPACE)
15
+
16
+ # Generates a page for step definitions and step transforms with the 'steptransformers' template
17
+ serialize(YARD::CodeObjects::Lucid::LUCID_STEPTRANSFORM_NAMESPACE)
18
+
19
+ # Generates the tags page with the 'featuretags' template
20
+ serialize(YARD::CodeObjects::Lucid::LUCID_TAG_NAMESPACE)
21
+
22
+ serialize_feature_directories
23
+ end
24
+
25
+ # The top-level feature directories. This is affected by the directories that
26
+ # YARD is told to parse. All other features in sub-directories are contained
27
+ # under each of these top-level directories.
28
+ #
29
+ # @example Generating one feature directory
30
+ #
31
+ # `yardoc 'example/**/*'`
32
+ #
33
+ # @example Generating two feature directories
34
+ #
35
+ # `yardoc 'features/**/*' 'specs/**/*'`
36
+ def root_feature_directories
37
+ @root_feature_directories ||= YARD::CodeObjects::Lucid::LUCID_NAMESPACE.children.find_all { |child| child.is_a?(YARD::CodeObjects::Lucid::FeatureDirectory) }
38
+ end
39
+
40
+ # Generate pages for the objects if there are objects of this type contained
41
+ # within the Registry.
42
+ def serialize_object_type(type)
43
+ objects = Registry.all(type.to_sym)
44
+ Array(objects).each { |object| serialize(object) }
45
+ end
46
+
47
+ # Generates pages for the feature directories found. Starting with all
48
+ # root-level feature directories and then recursively finding all child
49
+ # feature directories.
50
+ def serialize_feature_directories
51
+ serialize_feature_directories_recursively(root_feature_directories)
52
+ root_feature_directories.each { |directory| serialize(directory) }
53
+ end
54
+
55
+ # Generate a page for each Feature directory. This is called recursively to
56
+ # ensure that all feature directories contained as children are rendered to
57
+ # pages.
58
+ def serialize_feature_directories_recursively(namespaces)
59
+ namespaces.each do |namespace|
60
+ Templates::Engine.with_serializer(namespace, options[:serializer]) do
61
+ options[:object] = namespace
62
+ T('layout').run(options)
63
+ end
64
+ serialize_feature_directories_recursively(namespace.children.find_all { |child| child.is_a?(YARD::CodeObjects::Lucid::FeatureDirectory) })
65
+ end
66
+ end
67
+
68
+ # Generate feature list. This method is called automatically by YARD based on
69
+ # the menus defined in the layout.
70
+ def generate_feature_list
71
+ features = Registry.all(:feature)
72
+ features_ordered_by_name = features.sort {|x,y| x.value.to_s <=> y.value.to_s }
73
+ generate_full_list features_ordered_by_name, :features
74
+ end
75
+
76
+ # Generate tag list. This method is called automatically by YARD based on the
77
+ # menus defined in the layout
78
+ def generate_tag_list
79
+ tags = Registry.all(:tag)
80
+ tags_ordered_by_use = Array(tags).sort {|x,y| y.all_scenarios.size <=> x.all_scenarios.size }
81
+
82
+ generate_full_list tags_ordered_by_use, :tags
83
+ end
84
+
85
+ # Generate a step definition list. This menu is not automatically added until
86
+ # yard configuration has this menu added.
87
+ def generate_stepdefinition_list
88
+ generate_full_list YARD::Registry.all(:stepdefinition), :stepdefinitions,
89
+ :list_title => "Step Definitions List"
90
+ end
91
+
92
+ # Generate a step list. This menu is not automatically added until yard
93
+ # configuration has this menu added.
94
+ def generate_step_list
95
+ generate_full_list YARD::Registry.all(:step), :steps
96
+ end
97
+
98
+ # Generate feature list. This menu is not automatically added until yard
99
+ # configuration has this menu added.
100
+ def generate_featuredirectories_list
101
+ directories_ordered_by_name = root_feature_directories.sort { |x,y| x.value.to_s <=> y.value.to_s }
102
+ generate_full_list directories_ordered_by_name, :featuredirectories,
103
+ :list_title => "Features by Directory",
104
+ :list_filename => "featuredirectories_list.html"
105
+ end
106
+
107
+ # Helpler method to generate a full_list page of the specified objects with the
108
+ # specified type.
109
+ def generate_full_list(objects,type,options = {})
110
+ defaults = { :list_title => "#{type.to_s.capitalize} List",
111
+ :css_class => "class",
112
+ :list_filename => "#{type.to_s.gsub(/s$/,'')}_list.html" }
113
+
114
+ options = defaults.merge(options)
115
+
116
+ @items = objects
117
+ @list_type = type
118
+ @list_title = options[:list_title]
119
+ @list_class = options[:css_class]
120
+ asset options[:list_filename], erb(:full_list)
121
+ end
122
+
123
+ # This class provides the tree context needed by the server.
124
+ class TreeContext
125
+ def initialize
126
+ @depth = 0
127
+ @even_odd = Alternator.new(:even, :odd)
128
+ end
129
+
130
+ def nest
131
+ @depth += 1
132
+ yield
133
+ @depth -= 1
134
+ end
135
+
136
+ def indent
137
+ "#{(@depth + 2) * 15}px"
138
+ end
139
+
140
+ def classes
141
+ classes = []
142
+ classes << 'collapsed' if @depth > 0
143
+ classes << @even_odd.next if @depth < 2
144
+ classes
145
+ end
146
+
147
+ class Alternator
148
+ def initialize(first, second)
149
+ @next = first
150
+ @after = second
151
+ end
152
+
153
+ def next
154
+ @next, @after = @after, @next
155
+ @after
156
+ end
157
+ end
158
+ end
159
+
160
+ # This method overrides YARD's default template class_list method.
161
+ #
162
+ # The existing YARD 'Class List' search field contains all the YARD namespace
163
+ # objects. In the context of this parsing, the Lucid Namespace YARD Object is
164
+ # a meta-object, so that should not be considered.
165
+ #
166
+ # This method removes the namespace from the root node, generates the class
167
+ # list, and then adds it back into the root node.
168
+ def class_list(root = Registry.root, tree = TreeContext.new)
169
+ return super unless root == Registry.root
170
+
171
+ lucid_namespace = YARD::CodeObjects::Lucid::LUCID_NAMESPACE
172
+ root.instance_eval { children.delete lucid_namespace }
173
+ out = super(root)
174
+ root.instance_eval { children.push lucid_namespace }
175
+ out
176
+ end
177
+
178
+ # Generate a link to the 'All Features' in the features_list.html
179
+ #
180
+ # When there are no feature directories or multiple top-level feature
181
+ # directories, then link to the 'Requirements' page.
182
+ #
183
+ # When there are is just one feature directory then link to that directory.
184
+ def all_features_link
185
+ if root_feature_directories.length == 0 || root_feature_directories.length > 1
186
+ linkify YARD::CodeObjects::Lucid::LUCID_NAMESPACE, "All Features"
187
+ else
188
+ linkify root_feature_directories.first, "All Features"
189
+ end
190
+ end
191
+
192
+ # This method is used to generate a feature directory. This template may call
193
+ # this method as well to generate any child feature directories as well.
194
+ def directory_node(directory,padding,row)
195
+ @directory = directory
196
+ @padding = padding
197
+ @row = row
198
+ erb(:directories)
199
+ end