Top Level Namespace

Includes:
YARD::Templates::Helpers::HtmlHelper

Defined Under Namespace

Modules: Cucumber, YARD, YardTurnip

Instance Method Summary collapse

Instance Method Details

Generate a link to the ‘All Features’ in the features_list.html

When there are no feature directories or multiple top-level feature directories then we want to link to the ‘Requirements’ page

When there are is just one feature directory then we want to link to that directory



184
185
186
187
188
189
190
191
192
# File 'lib/templates/default/fulldoc/html/setup.rb', line 184

def all_features_link
  features = Registry.all(:feature)
  count_with_examples = record_feature_scenarios(features)
  if root_feature_directories.length == 0 || root_feature_directories.length > 1
    linkify YARD::CodeObjects::Cucumber::CUCUMBER_NAMESPACE, "All Features (#{count_with_examples})"
  else
    linkify root_feature_directories.first, "All Features (#{count_with_examples})"
  end
end

#all_tags_by_letterObject



11
12
13
14
15
16
17
# File 'lib/templates/default/featuretags/html/setup.rb', line 11

def all_tags_by_letter
  hash = {}
  objects = tags
  objects = run_verifier(objects)
  objects.each {|o| (hash[o.value.to_s[1,1].upcase] ||= []) << o }
  hash
end

#alpha_table(objects) ⇒ Object



17
18
19
20
21
22
23
24
25
26
27
# File 'lib/templates/default/tag/html/setup.rb', line 17

def alpha_table(objects)
  @elements = Hash.new

  objects = run_verifier(objects)
  objects.each {|o| (@elements[o.value.to_s[0,1].upcase] ||= []) << o }
  @elements.values.each {|v| v.sort! {|a,b| b.value.to_s <=> a.value.to_s } }
  @elements = @elements.sort_by {|l,o| l.to_s }

  @elements.each {|letter,objects| objects.sort! {|a,b| b.value.to_s <=> a.value.to_s }}
  erb(:alpha_table)
end

#backgroundObject



11
12
13
14
15
# File 'lib/templates/default/feature/html/setup.rb', line 11

def background
  @scenario = @feature.background
  @id = "background"
  erb(:scenario)
end

#class_list(root = Registry.root, tree = nil) ⇒ Object

Note:

This method overrides YARD’s default template class_list method.

The existing YARD ‘Class List’ search field contains all the YARD namespace objects. We, however, do not want the Cucumber Namespace YARD Object (which holds the features, tags, etc.) as it is a meta-object.

This method removes the namespace from the root node, generates the class list, and then adds it back into the root node.



166
167
168
169
170
171
172
173
174
# File 'lib/templates/default/fulldoc/html/setup.rb', line 166

def class_list(root = Registry.root, tree = nil)
  return super unless root == Registry.root

  cucumber_namespace = YARD::CodeObjects::Cucumber::CUCUMBER_NAMESPACE
  root.instance_eval { children.delete cucumber_namespace }
  out = super(root)
  root.instance_eval { children.push cucumber_namespace }
  out
end

#current_menu_listsObject

By default we want to display the ‘features’ and ‘tags’ menu but we will allow the YARD configuration to override that functionality.



40
41
42
43
44
45
46
47
48
49
50
# File 'lib/templates/default/layout/html/setup.rb', line 40

def current_menu_lists
  @current_menu_lists ||= begin
    menus = [ "features", "tags" ]

    if YARD::Config.options["yard-gherkin-turnip"] and YARD::Config.options["yard-gherkin-turnip"]["menus"]
      menus = YARD::Config.options["yard-gherkin-turnip"]["menus"]
    end

    menus
  end
end

#directoriesObject



15
16
17
# File 'lib/templates/default/featuredirectory/html/setup.rb', line 15

def directories
  @directories ||= @directory.subdirectories
end

#directory_node(directory, padding, row) ⇒ Object

This method is used to generate a feature directory. This template may call this method as well to generate any child feature directories as well.

Parameters:

  • directory (FeatureDirectory)

    this is the FeatureDirectory to display

  • padding (Fixnum)

    this is the pixel value to ident as we want to keep pushing in the padding to show the parent relationship

  • row (String)

    ‘odd’ or ‘even’ to correctly color the row



203
204
205
206
207
208
# File 'lib/templates/default/fulldoc/html/setup.rb', line 203

def directory_node(directory,padding,row)
  @directory = directory
  @padding = padding
  @row = row
  erb(:directories)
end

#display_comments_for(item) ⇒ Object



55
56
57
58
59
60
61
62
63
# File 'lib/templates/default/steptransformers/html/setup.rb', line 55

def display_comments_for(item)
  begin
    T('docstring').run(options.dup.merge({:object => item}))
  rescue
    log.warn %{An error occurred while attempting to render the comments for: #{item.location} }
    return ""
  end

end

#feature_directoriesObject



16
17
18
# File 'lib/templates/default/requirements/html/setup.rb', line 16

def feature_directories
  @feature_directories ||= YARD::CodeObjects::Cucumber::CUCUMBER_NAMESPACE.children.find_all {|child| child.is_a?(YARD::CodeObjects::Cucumber::FeatureDirectory)}
end

#feature_subdirectoriesObject



20
21
22
# File 'lib/templates/default/requirements/html/setup.rb', line 20

def feature_subdirectories
  @feature_subdirectories ||= Registry.all(:featuredirectory) - feature_directories
end

#feature_tags_with_all_scenario_tags(feature) ⇒ Object



27
28
29
# File 'lib/templates/default/featuretags/html/setup.rb', line 27

def feature_tags_with_all_scenario_tags(feature)
  feature.tags.collect {|t| t.value} + feature.scenarios.collect {|s| s.tags.collect {|t| t.value} }.flatten.uniq
end

#featuresObject



8
9
10
# File 'lib/templates/default/tag/html/setup.rb', line 8

def features
  @tag.features
end

#generate_feature_listObject

Note:

this method is called automatically by YARD based on the menus defined in the layout

Generate feature list



78
79
80
81
82
# File 'lib/templates/default/fulldoc/html/setup.rb', line 78

def generate_feature_list
  features = Registry.all(:feature)
  features_ordered_by_name = features.sort {|x,y| x.value.to_s <=> y.value.to_s }
  generate_full_list features_ordered_by_name, :features
end

#generate_featuredirectories_listObject

Note:

this menu is not automatically added until yard configuration has this menu added

Generate feature list See the layout template method that loads the menus



132
133
134
135
136
137
# File 'lib/templates/default/fulldoc/html/setup.rb', line 132

def generate_featuredirectories_list
  directories_ordered_by_name = root_feature_directories.sort {|x,y| x.value.to_s <=> y.value.to_s }
  generate_full_list directories_ordered_by_name, :featuredirectories,
    :list_title => "Features by Directory",
    :list_filename => "featuredirectories_list.html"
end

#generate_full_list(objects, type, options = {}) ⇒ Object

Helpler method to generate a full_list page of the specified objects with the specified type.



142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/templates/default/fulldoc/html/setup.rb', line 142

def generate_full_list(objects,type,options = {})
  defaults = { :list_title => "#{type.to_s.capitalize} List",
    :css_class => "class",
    :list_filename => "#{type.to_s.gsub(/s$/,'')}_list.html" }

  options = defaults.merge(options)

  @items = objects
  @list_type = type
  @list_title = options[:list_title]
  @list_class = options[:css_class]
  asset options[:list_filename], erb(:full_list)
end

#generate_step_listObject

Note:

this menu is not automatically added until yard configuration has this menu added

Generate a step list See the layout template method that loads the menus



125
126
127
# File 'lib/templates/default/fulldoc/html/setup.rb', line 125

def generate_step_list
  generate_full_list YARD::Registry.all(:step), :steps
end

#generate_stepdefinition_listObject

Note:

this menu is not automatically added until yard configuration has this menu added

Generate a step definition list See the layout template method that loads the menus



117
118
119
120
# File 'lib/templates/default/fulldoc/html/setup.rb', line 117

def generate_stepdefinition_list
  generate_full_list YARD::Registry.all(:stepdefinition), :stepdefinitions,
    :list_title => "Step Definitions List"
end

#generate_tag_listObject

Note:

this method is called automatically by YARD based on the menus defined in the layout

Generate tag list



105
106
107
108
109
110
111
112
# File 'lib/templates/default/fulldoc/html/setup.rb', line 105

def generate_tag_list
  tags = Registry.all(:tag)
  tags_ordered_by_use = Array(tags).sort {|x,y| y.total_scenarios <=> x.total_scenarios }

  record_tagged_scenarios(tags)

  generate_full_list tags_ordered_by_use, :tags
end

#highlight_matches(step) ⇒ Object



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/templates/default/feature/html/setup.rb', line 36

def highlight_matches(step)
  step.value.dup.tap do |value|
    if step.definition
      matches = step.definition.regex.match(step.value)
      if matches
        matches.named_captures.to_a.reverse.each_with_index do |(name,match),index|
          next if match == nil
          next unless name.start_with?("placeholder_")
          highlight = "<span class='match'>#{h(match)}</span>"
          value[matches.begin((matches.size - 1) - index)..(matches.end((matches.size - 1) - index) - 1)] = highlight
        end
      end
    end
  end
end

#highlight_transformed_step(step, placeholder) ⇒ Object



96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/templates/default/steptransformers/html/setup.rb', line 96

def highlight_transformed_step(step, placeholder)
  value = step.value.dup
  if step.definition
    matches = step.definition.regex.match(value)
    matches[1..-1].reverse.each_with_index do |match,index|
      next if match == nil
      next unless placeholder.regex.match?(match)
      value[matches.begin((matches.size - 1) - index)..(matches.end((matches.size - 1) - index) - 1)] = "<span class='match'>#{match}</span>"
    end
  end
  value
end

#htmlify_with_newlines(text) ⇒ Object



52
53
54
# File 'lib/templates/default/feature/html/setup.rb', line 52

def htmlify_with_newlines(text)
  text.split("\n").collect {|c| h(c).gsub(/\s/,'&nbsp;') }.join("<br/>")
end

#initObject



1
2
3
4
5
6
# File 'lib/templates/default/tag/html/setup.rb', line 1

def init
  super
  @tag = object

  sections.push :tag
end

#is_yard_cucumber_object?(object) ⇒ Boolean

Note:

quite a few of the classes/modules defined here are not object that we would never want to display but it’s alright if we match on them.

Determine if the object happens to be a CodeObject defined in this gem.

Returns:

  • (Boolean)

    true if the object’s class name is one of the CodeObjects



108
109
110
# File 'lib/templates/default/layout/html/setup.rb', line 108

def is_yard_cucumber_object?(object)
  YARD::CodeObjects::Cucumber.constants.any? {|constant| object.class.name == "YARD::CodeObjects::Cucumber::#{constant}" }
end

#javascriptsObject

Append yard-gherkin-turnip javascript to yard core javascripts



15
16
17
# File 'lib/templates/default/layout/html/setup.rb', line 15

def javascripts
  super + %w(js/cucumber.js)
end

#layoutObject

Note:

This method overrides YARD’s default layout template’s layout method.

The existing YARD layout method generates the url for the nav menu on the left side. For YARD-Gherkin-Turnip objects this will default to the class_list.html. which is not what we want for features, tags, etc.

So we override this method and put in some additional logic to figure out the correct list to appear in the search. This can be particularly tricky because

This method removes the namespace from the root node, generates the class list, and then adds it back into the root node.



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/templates/default/layout/html/setup.rb', line 79

def layout
  @nav_url = url_for_list(!@file || options.index ? 'class' : 'file')


  if is_yard_cucumber_object?(object)
    @nav_url = rewrite_nav_url(@nav_url)
  end

  if !object || object.is_a?(String)
    @path = nil
  elsif @file
    @path = @file.path
  elsif !object.is_a?(YARD::CodeObjects::NamespaceObject)
    @path = object.parent.path
  else
    @path = object.path
  end

  erb(:layout)
end


65
66
67
68
69
70
71
72
73
74
75
# File 'lib/templates/default/steptransformers/html/setup.rb', line 65

def link_step_definition_name(step_definition)
  value = step_definition.literal_value.dup

  if step_definition.placeholders
    value.gsub!(/:[\w]+/) do |match|
      placeholder = step_definition.placeholders.find {|placeholder| placeholder.literal_value == match }
      placeholder ? "<a href='#{url_for(placeholder)}'>#{h(match)}</a>" : "<span class='match'>#{match}</span>"
    end
  end
  value
end


78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/templates/default/steptransformers/html/setup.rb', line 78

def link_transformed_step(step)
  value = step.value.dup

  if step.definition
    matches = step.definition.regex.match(step.value)

    if matches
      matches[1..-1].reverse.each_with_index do |match,index|
        next if match == nil
        placeholder = step.placeholders.find {|placeholder| placeholder.regex.match(match) }

        value[matches.begin((matches.size - 1) - index)..(matches.end((matches.size - 1) - index) - 1)] = placeholder ? "<a href='#{url_for(placeholder)}'>#{h(match)}</a>" : "<span class='match'>#{h(match)}</span>"
      end
    end
  end
  value
end

#markdown(text) ⇒ Object



7
8
9
# File 'lib/templates/default/featuredirectory/html/setup.rb', line 7

def markdown(text)
  htmlify(text,:markdown) rescue h(text)
end

Append yard-gherkin-turnip specific menus ‘features’ and ‘tags’

‘features’ and ‘tags’ are enabled by default.

‘step definitions’ and ‘steps’ may be enabled by setting up a value in yard configuration file ‘~/.yard/config’

Examples:

‘~/.yard/config`


yard-gherkin-turnip:
  menus: [ 'features', 'directories', 'tags', 'step definitions', 'steps' ]


32
33
34
# File 'lib/templates/default/layout/html/setup.rb', line 32

def menu_lists
  current_menu_lists.map {|menu_name| yard_turnip_menus[menu_name] }.compact + super
end

#namespaceObject



7
8
9
# File 'lib/templates/default/featuretags/html/setup.rb', line 7

def namespace
  erb(:namespace)
end

#placeholdersObject



32
33
34
# File 'lib/templates/default/requirements/html/setup.rb', line 32

def placeholders
  @placeholders ||= YARD::Registry.all(:placeholder)
end

#placeholders_sectionObject



32
33
34
35
36
37
38
# File 'lib/templates/default/steptransformers/html/setup.rb', line 32

def placeholders_section
  @item_title = "Placeholders"
  @item_anchor_name = "placeholders"
  @item_type = "placeholder"
  @items = placeholders
  erb(:header) + erb(:placeholders)
end

#record_feature_scenarios(features) ⇒ Object

Count scenarios for features



85
86
87
88
89
90
91
# File 'lib/templates/default/fulldoc/html/setup.rb', line 85

def record_feature_scenarios(features)
  count_with_examples = 0
  features.each do |f|
    count_with_examples += f.total_scenarios
  end
  return count_with_examples
end

#record_tagged_scenarios(tags) ⇒ Object

Count scenarios for tags



94
95
96
97
98
99
100
101
# File 'lib/templates/default/fulldoc/html/setup.rb', line 94

def record_tagged_scenarios(tags)
  scenario_count = 0
  count_with_examples = 0
  tags.each do |t|
    scenario_count += t.all_scenarios.size
    count_with_examples += t.total_scenarios
  end
end

#rewrite_nav_url(nav_url) ⇒ Object

The re-write rules will only change the nav link to a new menu if it is a a Cucumber CodeObject that we care about and that we have also generated a menu for that item.



117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/templates/default/layout/html/setup.rb', line 117

def rewrite_nav_url(nav_url)
  if object.is_a?(YARD::CodeObjects::Cucumber::Feature) && current_menu_lists.include?('features')
    nav_url.gsub('class_list.html','feature_list.html')
  elsif object.is_a?(YARD::CodeObjects::Cucumber::FeatureDirectory) && current_menu_lists.include?('directories')
    nav_url.gsub('class_list.html','featuredirectories_list.html')
  elsif object.is_a?(YARD::CodeObjects::Cucumber::Tag) && current_menu_lists.include?('tags')
    nav_url.gsub('class_list.html','tag_list.html')
  elsif object.is_a?(YARD::CodeObjects::Cucumber::Step) && current_menu_lists.include?('steps')
    nav_url.gsub('class_list.html','step_list.html')
  elsif object.is_a?(YARD::CodeObjects::Cucumber::StepTransformers) && current_menu_lists.include?('step definitions')
    nav_url.gsub('class_list.html','stepdefinition_list.html')
  else
    nav_url
  end
end

#root_feature_directoriesObject

The top-level feature directories. This is affected by the directories that YARD is told to parse. All other features in sub-directories are contained under each of these top-level directories.

Examples:

Generating one feature directory


`yardoc 'example/**/*'`

Generating two feature directories


`yardoc 'example/**/*' 'example2/**/*'`

Returns:

  • the feature directories at the root of the Cucumber Namespace.



39
40
41
# File 'lib/templates/default/fulldoc/html/setup.rb', line 39

def root_feature_directories
  @root_feature_directories ||= YARD::CodeObjects::Cucumber::CUCUMBER_NAMESPACE.children.find_all {|child| child.is_a?(YARD::CodeObjects::Cucumber::FeatureDirectory)}
end

#scenariosObject



12
13
14
# File 'lib/templates/default/tag/html/setup.rb', line 12

def scenarios
  @tag.scenarios
end

#serialize_feature_directoriesObject

Generates pages for the feature directories found. Starting with all root-level feature directories and then recursively finding all child feature directories.



56
57
58
59
# File 'lib/templates/default/fulldoc/html/setup.rb', line 56

def serialize_feature_directories
  serialize_feature_directories_recursively(root_feature_directories)
  root_feature_directories.each {|directory| serialize(directory) }
end

#serialize_feature_directories_recursively(namespaces) ⇒ Object

Generate a page for each Feature Directory. This is called recursively to ensure that all feature directories contained as children are rendered to pages.



66
67
68
69
70
71
72
73
74
# File 'lib/templates/default/fulldoc/html/setup.rb', line 66

def serialize_feature_directories_recursively(namespaces)
  namespaces.each do |namespace|
    Templates::Engine.with_serializer(namespace, options[:serializer]) do
      options[:object] = namespace
      T('layout').run(options)
    end
    serialize_feature_directories_recursively(namespace.children.find_all {|child| child.is_a?(YARD::CodeObjects::Cucumber::FeatureDirectory)})
  end
end

#serialize_object_type(type) ⇒ Object

Generate pages for the objects if there are objects of this type contained within the Registry.



47
48
49
50
# File 'lib/templates/default/fulldoc/html/setup.rb', line 47

def serialize_object_type(type)
  objects = Registry.all(type.to_sym)
  Array(objects).each {|object| serialize(object) }
end

#step_definitionsObject



28
29
30
# File 'lib/templates/default/requirements/html/setup.rb', line 28

def step_definitions
  @step_definitions ||= YARD::Registry.all(:stepdefinition)
end

#step_definitions_sectionObject



24
25
26
27
28
29
30
# File 'lib/templates/default/steptransformers/html/setup.rb', line 24

def step_definitions_section
  @item_title = "Step Definitions"
  @item_anchor_name = "step_definitions"
  @item_type = "step definition"
  @items = step_definitions
  erb(:header) + erb(:step_definitions)
end

#step_transformersObject



24
25
26
# File 'lib/templates/default/requirements/html/setup.rb', line 24

def step_transformers
  YARD::CodeObjects::Cucumber::CUCUMBER_STEPTRANSFORM_NAMESPACE
end

#stylesheetsObject

Append yard-gherkin-turnip stylesheet to yard core stylesheets



8
9
10
# File 'lib/templates/default/layout/html/setup.rb', line 8

def stylesheets
  super + %w(css/cucumber.css)
end

#tagify(tag) ⇒ Object



32
33
34
# File 'lib/templates/default/featuretags/html/setup.rb', line 32

def tagify(tag)
  %{<span class="tag" href="#{url_for tag}">#{tag.value}</span>}
end

#tagsObject



19
20
21
# File 'lib/templates/default/featuretags/html/setup.rb', line 19

def tags
  @tags ||= Registry.all(:tag).sort_by {|l| l.value.to_s }
end

#undefined_stepsObject



36
37
38
# File 'lib/templates/default/requirements/html/setup.rb', line 36

def undefined_steps
  @undefined_steps ||= Registry.all(:step).reject {|s| s.definition || s.scenario.outline? }
end

#undefined_steps_sectionObject



40
41
42
43
44
45
46
# File 'lib/templates/default/steptransformers/html/setup.rb', line 40

def undefined_steps_section
  @item_title = "Undefined Steps"
  @item_anchor_name = "undefined_steps"
  @item_type = nil
  @items = undefined_steps
  erb(:header) + erb(:undefined_steps)
end

#unique_steps(steps) ⇒ Object



49
50
51
52
53
# File 'lib/templates/default/steptransformers/html/setup.rb', line 49

def unique_steps(steps)
  uniq_steps = {}
  steps.each {|s| (uniq_steps[s.value.to_s] ||= []) << s }
  uniq_steps
end

#yard_turnip_menusObject

When a menu is specified in the yard configuration file, this hash contains the details about the menu necessary for it to be displayed.

See Also:



58
59
60
61
62
63
64
# File 'lib/templates/default/layout/html/setup.rb', line 58

def yard_turnip_menus
  { "features" => { :type => 'feature', :title => 'Features', :search_title => 'Features' },
    "directories" => { :type => 'featuredirectories', :title => 'Features by Directory', :search_title => 'Features by Directory' },
    "tags" => { :type => 'tag', :title => 'Tags', :search_title => 'Tags' },
    "step definitions" => { :type => 'stepdefinition', :title => 'Step Definitions', :search_title => 'Step Defs' },
    "steps" => { :type => 'step', :title => 'Steps', :search_title => 'Steps' } }
end