From b08df5827b0818df2e9d1e5fa9f161350d5bbb70 Mon Sep 17 00:00:00 2001 From: Daniel Parks Date: Fri, 23 Sep 2022 03:08:55 -0700 Subject: [PATCH] (#300) Fix anchor links in Markdown docs Previously, anchors in generated Markdown were not unique. There were two problems: 1. Each parameter in a class, type, function, etc. had its own anchor, but the `name` of the anchor was just the normalized name of the parameter. This meant that all parameters with the same name would have the same anchor. 2. Classes, types, etc. had their `::`s removed, whiched opened the (rare) possibility of having non-unique anchor names for unique type names. This fixes those problems by: 1. Using the full name of the parameter, e.g. `$my::class::param`, to generate an anchor name. 2. Using a better anchor normalization routine. Each invalid character, i.e. not `[a-zA-Z0-9_-]`, is converted to `-`. This should always result in unique anchor names for standard Puppet identifiers, since the only invalid characters sequences are `::` and `$` (which only appears once at the beginning of the string). Furthermore, `-` never appears in a valid Puppet identifier, so those two cases are the only way for it to be generated. --- lib/puppet-strings/markdown/base.rb | 20 +++++++++++++++++-- lib/puppet-strings/markdown/resource_type.rb | 10 ++++++++-- .../templates/classes_and_defines.erb | 4 ++-- .../markdown/templates/data_type.erb | 4 ++-- .../markdown/templates/resource_type.erb | 4 ++-- .../unit/puppet-strings/markdown/base_spec.rb | 2 +- 6 files changed, 33 insertions(+), 11 deletions(-) diff --git a/lib/puppet-strings/markdown/base.rb b/lib/puppet-strings/markdown/base.rb index f99adeacd..a98256ca9 100644 --- a/lib/puppet-strings/markdown/base.rb +++ b/lib/puppet-strings/markdown/base.rb @@ -95,7 +95,11 @@ def see # @return [Array] parameter tag hashes def params - select_tags('param') + tags = @tags.select { |tag| tag[:tag_name] == 'param' }.map do |param| + param[:link] = clean_link("$#{name}::#{param[:name]}") + param + end + tags.empty? ? nil : tags end # @return [Array] example tag hashes @@ -151,7 +155,7 @@ def toc_info # @return [String] makes the component name suitable for a GitHub markdown link def link - name.delete('::').strip.gsub(' ','-').downcase + clean_link(name) end # Some return, default, or valid values need to be in backticks. Instead of fu in the handler or code_object, this just does the change on the front. @@ -195,5 +199,17 @@ def select_tags(name) tags = @tags.select { |tag| tag[:tag_name] == name } tags.empty? ? nil : tags end + + # Convert an input into a string appropriate for an anchor name. + # + # This converts any character not suitable for an id attribute into a '-'. Generally we're running this on Puppet identifiers for types and + # variables, so we only need to worry about the special characters ':' and '$'. With namespaces Puppet variables this should always be produce a + # unique result from a unique input, since ':' only appears in pairs, '$' only appears at the beginning, and '-' never appears. + # + # @param [String] the input to convert + # @return [String] the anchor-safe string + def clean_link(input) + input.tr('^a-zA-Z0-9_-', '-') + end end end diff --git a/lib/puppet-strings/markdown/resource_type.rb b/lib/puppet-strings/markdown/resource_type.rb index f1b4393b3..1d959cb67 100644 --- a/lib/puppet-strings/markdown/resource_type.rb +++ b/lib/puppet-strings/markdown/resource_type.rb @@ -29,13 +29,19 @@ def checks def properties_and_checks return nil if properties.nil? && checks.nil? - ((properties || []) + (checks || [])).sort_by { |p| p[:name] } + ((properties || []) + (checks || [])).sort_by { |p| p[:name] }.map do |prop| + prop[:link] = clean_link("$#{name}::#{prop[:name]}") + prop + end end def parameters return nil unless @registry[:parameters] - @registry[:parameters].sort_by { |p| p[:name] } + @registry[:parameters].sort_by { |p| p[:name] }.map do |param| + param[:link] = clean_link("$#{name}::#{param[:name]}") + param + end end def regex_in_data_type?(data_type) diff --git a/lib/puppet-strings/markdown/templates/classes_and_defines.erb b/lib/puppet-strings/markdown/templates/classes_and_defines.erb index e73993268..2b4f19b5d 100644 --- a/lib/puppet-strings/markdown/templates/classes_and_defines.erb +++ b/lib/puppet-strings/markdown/templates/classes_and_defines.erb @@ -50,11 +50,11 @@ The following parameters are available in the `<%= name %>` <%= @type %>: <% params.each do |param| -%> -* [`<%= param[:name] %>`](#<%= param[:name] %>) +* [`<%= param[:name] %>`](#<%= param[:link] %>) <% end -%> <% params.each do |param| -%> -##### `<%= param[:name] %>` +##### `<%= param[:name] %>` <% if param[:types] -%> Data type: `<%= param[:types].join(', ') -%>` diff --git a/lib/puppet-strings/markdown/templates/data_type.erb b/lib/puppet-strings/markdown/templates/data_type.erb index eaf6e842e..160f17cdd 100644 --- a/lib/puppet-strings/markdown/templates/data_type.erb +++ b/lib/puppet-strings/markdown/templates/data_type.erb @@ -58,11 +58,11 @@ Alias of The following parameters are available in the `<%= name %>` <%= @type %>: <% params.each do |param| -%> -* [`<%= param[:name] %>`](#<%= param[:name] %>) +* [`<%= param[:name] %>`](#<%= param[:link] %>) <% end -%> <% params.each do |param| -%> -##### `<%= param[:name] %>` +##### `<%= param[:name] %>` <% if param[:types] -%> Data type: `<%= param[:types].join(', ') -%>` diff --git a/lib/puppet-strings/markdown/templates/resource_type.erb b/lib/puppet-strings/markdown/templates/resource_type.erb index e9f1be1ab..8490967be 100644 --- a/lib/puppet-strings/markdown/templates/resource_type.erb +++ b/lib/puppet-strings/markdown/templates/resource_type.erb @@ -98,11 +98,11 @@ Default value: `<%= prop[:default] %>` The following parameters are available in the `<%= name %>` <%= @type %>. <% parameters.each do |param| -%> -* [`<%= param[:name] %>`](#<%= param[:name] %>) +* [`<%= param[:name] %>`](#<%= param[:link] %>) <% end -%> <% parameters.each do |param| -%> -##### `<%= param[:name] %>` +##### `<%= param[:name] %>` <% if param[:values] -%> Valid values: `<%= param[:values].map { |value| value_string(value) }.join('`, `') %>` diff --git a/spec/unit/puppet-strings/markdown/base_spec.rb b/spec/unit/puppet-strings/markdown/base_spec.rb index b9723e762..d46aa63a0 100644 --- a/spec/unit/puppet-strings/markdown/base_spec.rb +++ b/spec/unit/puppet-strings/markdown/base_spec.rb @@ -141,7 +141,7 @@ class klass::yeah( describe '#link' do it 'returns a valid link' do - expect(component.link).to eq 'klassyeah' + expect(component.link).to eq 'klass--yeah' end end end