jekyll-relative-links 0.6.1 → 0.8.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6a52004700c904303c029534ffabb2d4219b2680f0f0ab3e6503bec3590a03b5
4
- data.tar.gz: a4f0aaeeec9d1613304f0592dda8eff220a9efb9a94a1d48ab6b8058b4a08ead
3
+ metadata.gz: 3ebb41a644bab20c56e388f5b63e9fcaea9e8405de7c6af7853b7b30ca80b5bd
4
+ data.tar.gz: 12fd6b72f8fe9acde53c5fe8059a409610b6d808d63c888e7585de25b93a2160
5
5
  SHA512:
6
- metadata.gz: cd5cea8919a1a671a6809abd815556339e193c9c0ed69cf27f10674124cd47f087f032df68cdacfa3b17058fbda2ad707b7bb9a845a118347f3a81dc737c2bb2
7
- data.tar.gz: 0b837f08ffc3e18e0e5c49186c7cb2ba8a2d05093ad67084e07562c5aaa88578a0e41169fbaf16b6f6e3edd26d550fd5b0a14afc81ff82deadcd547fc6364700
6
+ metadata.gz: eb15617682d0df090db9ab9a25ae69c9fd8d50188a2ec49d7fa1a873d01e3ddbf638085ec0620c2a6cdc1a65f38e15f7615385c0132da974c496d0dab7f1b455
7
+ data.tar.gz: 5acc91f26ba6c9ee15341bf0575fc72c7ec4174166cbbc1c602ed80384a518702b74558b61dae9b0ac8f1cbcbb3c2c01eefc98d136dad5b04e0ed8b8170b0447
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JekyllRelativeLinks
4
+ module Filter
5
+ # This filter processes HTML content that's already been converted by the markdownify
6
+ # filter and updates any relative links to markdown files to point to their HTML equivalents.
7
+ # Usage: {{ content | markdownify | rellinks }}
8
+ def rellinks(html)
9
+ return html if html.nil? || html.empty?
10
+ return html if @context.registers[:site].nil?
11
+
12
+ process_links(html, @context.registers[:site])
13
+ end
14
+
15
+ def process_links(html, site)
16
+ page = @context.registers[:page]
17
+ url_base = page ? File.dirname(page["path"].to_s) : ""
18
+
19
+ html.gsub(%r!<a href="([^"]+\.md)(#([^"]+))?"!) do |match|
20
+ process_link(match, Regexp.last_match, url_base, site)
21
+ end
22
+ end
23
+
24
+ def process_link(match, regex_match, url_base, site)
25
+ relative_path = regex_match[1]
26
+ fragment = regex_match[3] ? "##{regex_match[3]}" : ""
27
+
28
+ return match if absolute_url?(relative_path) || !relative_path.end_with?(".md")
29
+
30
+ path = path_from_root(relative_path, url_base)
31
+ url = url_for_path(path, site)
32
+ url ? "<a href=\"#{url}#{fragment}\"" : match
33
+ end
34
+
35
+ private
36
+
37
+ def absolute_url?(string)
38
+ return false unless string
39
+
40
+ Addressable::URI.parse(string).absolute?
41
+ rescue Addressable::URI::InvalidURIError
42
+ false
43
+ end
44
+
45
+ def path_from_root(relative_path, url_base)
46
+ is_absolute = relative_path.start_with? "/"
47
+
48
+ relative_path.delete_prefix!("/")
49
+ base = is_absolute ? "" : url_base
50
+ absolute_path = File.expand_path(relative_path, base)
51
+ absolute_path.sub(%r!\A#{Regexp.escape(Dir.pwd)}/!, "")
52
+ end
53
+
54
+ def url_for_path(path, site)
55
+ path = CGI.unescape(path)
56
+ potential_targets = site.pages + site.static_files + site.docs_to_write
57
+ target = potential_targets.find { |p| p.relative_path.delete_prefix("/") == path }
58
+ relative_url(target.url) if target&.url
59
+ end
60
+ end
61
+ end
62
+
63
+ Liquid::Template.register_filter(JekyllRelativeLinks::Filter)
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "cgi"
4
+
3
5
  module JekyllRelativeLinks
4
6
  class Generator < Jekyll::Generator
5
7
  attr_accessor :site, :config
@@ -7,10 +9,17 @@ module JekyllRelativeLinks
7
9
  # Use Jekyll's native relative_url filter
8
10
  include Jekyll::Filters::URLFilters
9
11
 
10
- LINK_TEXT_REGEX = %r!(.*?)!.freeze
11
- FRAGMENT_REGEX = %r!(#.+?)?!.freeze
12
- INLINE_LINK_REGEX = %r!\[#{LINK_TEXT_REGEX}\]\(([^\)]+?)#{FRAGMENT_REGEX}\)!.freeze
13
- REFERENCE_LINK_REGEX = %r!^\s*?\[#{LINK_TEXT_REGEX}\]: (.+?)#{FRAGMENT_REGEX}\s*?$!.freeze
12
+ # Matches link text, including images like ![alt](url) or ![alt]
13
+ # Pattern explanation:
14
+ # - !\[[^\]]*\](?:\([^\)]*\))? matches complete image patterns: ![...](...) or ![...]
15
+ # - (?!\]\() uses negative lookahead to match any char except when followed by ](
16
+ # This allows nested ] while stopping at the correct closing bracket
17
+ LINK_TEXT_REGEX = %r{((?:!\[[^\]]*\](?:\([^\)]*\))?|(?!\]\().)*?)}.freeze
18
+ FRAGMENT_REGEX = %r!(#.+?|)?!.freeze
19
+ TITLE_REGEX = %r{(\s+"(?:\\"|[^"])*(?<!\\)"|\s+"(?:\\'|[^'])*(?<!\\)')?}.freeze
20
+ FRAG_AND_TITLE_REGEX = %r!#{FRAGMENT_REGEX}#{TITLE_REGEX}!.freeze
21
+ INLINE_LINK_REGEX = %r!\[#{LINK_TEXT_REGEX}\]\(([^)]+?)#{FRAG_AND_TITLE_REGEX}\)!.freeze
22
+ REFERENCE_LINK_REGEX = %r!^\s*?\[#{LINK_TEXT_REGEX}\]: (.+?)#{FRAG_AND_TITLE_REGEX}\s*?$!.freeze
14
23
  LINK_REGEX = %r!(#{INLINE_LINK_REGEX}|#{REFERENCE_LINK_REGEX})!.freeze
15
24
  CONVERTER_CLASS = Jekyll::Converters::Markdown
16
25
  CONFIG_KEY = "relative_links"
@@ -48,27 +57,35 @@ module JekyllRelativeLinks
48
57
  return document if document.content.nil?
49
58
 
50
59
  document.content = document.content.dup.gsub(LINK_REGEX) do |original|
51
- link_type, link_text, relative_path, fragment = link_parts(Regexp.last_match)
52
- next original unless replaceable_link?(relative_path)
60
+ link = link_parts(Regexp.last_match)
61
+ next original unless replaceable_link?(link.path)
53
62
 
54
- path = path_from_root(relative_path, url_base)
63
+ path = path_from_root(CGI.unescape(link.path), url_base)
55
64
  url = url_for_path(path)
56
65
  next original unless url
57
66
 
58
- replacement_text(link_type, link_text, url, fragment)
67
+ link.path = url
68
+ replacement_text(link)
59
69
  end
70
+
71
+ replace_relative_links_excerpt!(document)
60
72
  rescue ArgumentError => e
61
73
  raise e unless e.to_s.start_with?("invalid byte sequence in UTF-8")
62
74
  end
63
75
 
64
76
  private
65
77
 
78
+ # Stores info on a Markdown Link (avoid rubocop's Metrics/ParameterLists warning)
79
+ Link = Struct.new(:link_type, :text, :path, :fragment, :title)
80
+
66
81
  def link_parts(matches)
67
- link_type = matches[2] ? :inline : :reference
68
- link_text = matches[link_type == :inline ? 2 : 5]
69
- relative_path = matches[link_type == :inline ? 3 : 6]
70
- fragment = matches[link_type == :inline ? 4 : 7]
71
- [link_type, link_text, relative_path, fragment]
82
+ last_inline = 5
83
+ link_type = matches[2] ? :inline : :reference
84
+ link_text = matches[link_type == :inline ? 2 : last_inline + 1]
85
+ relative_path = matches[link_type == :inline ? 3 : last_inline + 2]
86
+ fragment = matches[link_type == :inline ? 4 : last_inline + 3]
87
+ title = matches[link_type == :inline ? 5 : last_inline + 4]
88
+ Link.new(link_type, link_text, relative_path, fragment, title)
72
89
  end
73
90
 
74
91
  def context
@@ -84,7 +101,7 @@ module JekyllRelativeLinks
84
101
  end
85
102
 
86
103
  def url_for_path(path)
87
- target = potential_targets.find { |p| p.relative_path.sub(%r!\A/!, "") == path }
104
+ target = potential_targets_by_path[path]
88
105
  relative_url(target.url) if target&.url
89
106
  end
90
107
 
@@ -92,28 +109,45 @@ module JekyllRelativeLinks
92
109
  @potential_targets ||= site.pages + site.static_files + site.docs_to_write
93
110
  end
94
111
 
112
+ # Index `potential_targets` by the same key the previous linear `find`
113
+ # compared against, so each `url_for_path` lookup is O(1) instead of
114
+ # O(N). On a site with M markdown link matches and N potential
115
+ # targets, total link-resolution cost goes from O(M*N) to O(M+N).
116
+ # First-wins semantics are preserved against the (unlikely) case of
117
+ # two targets sharing the same `relative_path`.
118
+ def potential_targets_by_path
119
+ @potential_targets_by_path ||= potential_targets.each_with_object({}) do |p, h|
120
+ key = p.relative_path.sub(%r!\A/!, "")
121
+ h[key] = p unless h.key?(key)
122
+ end
123
+ end
124
+
95
125
  def path_from_root(relative_path, url_base)
126
+ is_absolute = relative_path.start_with? "/"
127
+
96
128
  relative_path.sub!(%r!\A/!, "")
97
- absolute_path = File.expand_path(relative_path, url_base)
129
+ base = is_absolute ? "" : url_base
130
+ absolute_path = File.expand_path(relative_path, base)
98
131
  absolute_path.sub(%r!\A#{Regexp.escape(Dir.pwd)}/!, "")
99
132
  end
100
133
 
101
- def replacement_text(type, text, url, fragment = nil)
102
- url << fragment if fragment
134
+ # @param link [Link] A Link object describing the markdown link to make
135
+ def replacement_text(link)
136
+ link.path << link.fragment if link.fragment
103
137
 
104
- if type == :inline
105
- "[#{text}](#{url})"
138
+ if link.link_type == :inline
139
+ "[#{link.text}](#{link.path}#{link.title})"
106
140
  else
107
- "\n[#{text}]: #{url}"
141
+ "\n[#{link.text}]: #{link.path}#{link.title}"
108
142
  end
109
143
  end
110
144
 
111
145
  def absolute_url?(string)
112
- return unless string
146
+ return false unless string
113
147
 
114
148
  Addressable::URI.parse(string).absolute?
115
149
  rescue Addressable::URI::InvalidURIError
116
- nil
150
+ false
117
151
  end
118
152
 
119
153
  def fragment?(string)
@@ -153,5 +187,11 @@ module JekyllRelativeLinks
153
187
  def global_entry_filter
154
188
  @global_entry_filter ||= Jekyll::EntryFilter.new(site)
155
189
  end
190
+
191
+ def replace_relative_links_excerpt!(document)
192
+ return unless document.data["excerpt"] && !document.data["excerpt"].is_a?(String)
193
+
194
+ document.data["excerpt"] = Jekyll::Excerpt.new(document)
195
+ end
156
196
  end
157
197
  end
@@ -0,0 +1,124 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JekyllRelativeLinks
4
+ # Register Jekyll hooks to process HTML output after conversion
5
+ Jekyll::Hooks.register :pages, :post_render do |page|
6
+ next unless JekyllRelativeLinks::Hooks.should_process?(page, page.site.config)
7
+
8
+ page.output = JekyllRelativeLinks::Hooks.process_html_links(page.output, page, page.site)
9
+ end
10
+
11
+ Jekyll::Hooks.register :documents, :post_render do |document|
12
+ next unless JekyllRelativeLinks::Hooks.should_process_document?(document, document.site.config)
13
+
14
+ document.output = JekyllRelativeLinks::Hooks.process_html_links(document.output, document,
15
+ document.site)
16
+ end
17
+
18
+ module Hooks
19
+ CONVERTER_CLASS = Jekyll::Converters::Markdown
20
+ CONFIG_KEY = "relative_links"
21
+ ENABLED_KEY = "enabled"
22
+ COLLECTIONS_KEY = "collections"
23
+
24
+ # Regex to match markdown links in HTML: <a href="*.md">
25
+ # Capture groups:
26
+ # (1) attributes before href, (2) the .md path,
27
+ # (3) optional fragment, (4) attributes after href
28
+ MARKDOWN_LINK_IN_HTML = %r!<a\s+([^>]*?\s+)?href="([^"]+\.md)(#[^"]*)?"\s*([^>]*)>!m.freeze
29
+
30
+ def self.should_process?(page, config)
31
+ return false if disabled?(config)
32
+ return false unless markdown_extension?(page.extname, page.site)
33
+ return false if excluded?(page, config, page.site)
34
+
35
+ true
36
+ end
37
+
38
+ def self.should_process_document?(document, config)
39
+ return false if disabled?(config)
40
+ return false unless collections_enabled?(config)
41
+ return false unless markdown_extension?(document.extname, document.site)
42
+ return false if excluded?(document, config, document.site)
43
+
44
+ true
45
+ end
46
+
47
+ def self.disabled?(config)
48
+ config[CONFIG_KEY] && config[CONFIG_KEY][ENABLED_KEY] == false
49
+ end
50
+
51
+ def self.collections_enabled?(config)
52
+ config[CONFIG_KEY] && config[CONFIG_KEY][COLLECTIONS_KEY] == true
53
+ end
54
+
55
+ def self.markdown_extension?(extension, site)
56
+ converter = site.find_converter_instance(CONVERTER_CLASS)
57
+ converter.matches(extension)
58
+ end
59
+
60
+ def self.excluded?(document, config, site)
61
+ return false unless config[CONFIG_KEY] && config[CONFIG_KEY]["exclude"]
62
+
63
+ entry_filter = if document.respond_to?(:collection)
64
+ document.collection.entry_filter
65
+ else
66
+ Jekyll::EntryFilter.new(site)
67
+ end
68
+
69
+ entry_filter.glob_include?(config[CONFIG_KEY]["exclude"], document.relative_path)
70
+ end
71
+
72
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
73
+ def self.process_html_links(html, document, site)
74
+ return html if html.nil? || html.empty?
75
+
76
+ url_base = File.dirname(document.relative_path)
77
+ potential_targets = site.pages + site.static_files + site.docs_to_write
78
+
79
+ # Process <a href="*.md"> links that were added via includes
80
+ # rubocop:disable Metrics/BlockLength
81
+ html.gsub(MARKDOWN_LINK_IN_HTML) do |match|
82
+ attributes_before = Regexp.last_match[1] || ""
83
+ relative_path = Regexp.last_match[2]
84
+ fragment = Regexp.last_match[3] || ""
85
+ attributes_after = Regexp.last_match[4] || ""
86
+
87
+ # Skip absolute URLs
88
+ begin
89
+ next match if Addressable::URI.parse(relative_path).absolute?
90
+ rescue Addressable::URI::InvalidURIError
91
+ next match
92
+ end
93
+
94
+ # Calculate path from root
95
+ is_absolute = relative_path.start_with?("/")
96
+ relative_path_clean = relative_path.delete_prefix("/")
97
+ base = is_absolute ? "" : url_base
98
+ absolute_path = File.expand_path(relative_path_clean, base)
99
+ path = absolute_path.sub(%r!\A#{Regexp.escape(Dir.pwd)}/!, "")
100
+
101
+ # Find the target page and get its URL
102
+ path = CGI.unescape(path)
103
+ target = potential_targets.find { |p| p.relative_path.delete_prefix("/") == path }
104
+
105
+ if target&.url
106
+ # Use Jekyll's URL
107
+ url = target.url
108
+ url = "/#{url}" unless url.start_with?("/")
109
+
110
+ # Build the replacement ensuring proper spacing
111
+ attrs = []
112
+ attrs << attributes_before.strip unless attributes_before.empty?
113
+ attrs << "href=\"#{url}#{fragment}\""
114
+ attrs << attributes_after.strip unless attributes_after.empty?
115
+ "<a #{attrs.join(" ")}>"
116
+ else
117
+ match
118
+ end
119
+ end
120
+ # rubocop:enable Metrics/BlockLength
121
+ end
122
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
123
+ end
124
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module JekyllRelativeLinks
4
- VERSION = "0.6.1"
4
+ VERSION = "0.8.0"
5
5
  end
@@ -3,6 +3,8 @@
3
3
  require "jekyll"
4
4
  require_relative "jekyll-relative-links/generator"
5
5
  require_relative "jekyll-relative-links/context"
6
+ require_relative "jekyll-relative-links/filter"
7
+ require_relative "jekyll-relative-links/hooks"
6
8
 
7
9
  module JekyllRelativeLinks
8
10
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jekyll-relative-links
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.1
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Balter
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2019-10-23 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: jekyll
@@ -30,6 +29,20 @@ dependencies:
30
29
  - - "<"
31
30
  - !ruby/object:Gem::Version
32
31
  version: '5.0'
32
+ - !ruby/object:Gem::Dependency
33
+ name: kramdown-parser-gfm
34
+ requirement: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - "~>"
37
+ - !ruby/object:Gem::Version
38
+ version: '1.0'
39
+ type: :development
40
+ prerelease: false
41
+ version_requirements: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - "~>"
44
+ - !ruby/object:Gem::Version
45
+ version: '1.0'
33
46
  - !ruby/object:Gem::Dependency
34
47
  name: rspec
35
48
  requirement: !ruby/object:Gem::Requirement
@@ -50,14 +63,28 @@ dependencies:
50
63
  requirements:
51
64
  - - "~>"
52
65
  - !ruby/object:Gem::Version
53
- version: '0.71'
66
+ version: '1.0'
67
+ type: :development
68
+ prerelease: false
69
+ version_requirements: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - "~>"
72
+ - !ruby/object:Gem::Version
73
+ version: '1.0'
74
+ - !ruby/object:Gem::Dependency
75
+ name: rubocop-factory_bot
76
+ requirement: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - "~>"
79
+ - !ruby/object:Gem::Version
80
+ version: 2.26.0
54
81
  type: :development
55
82
  prerelease: false
56
83
  version_requirements: !ruby/object:Gem::Requirement
57
84
  requirements:
58
85
  - - "~>"
59
86
  - !ruby/object:Gem::Version
60
- version: '0.71'
87
+ version: 2.26.0
61
88
  - !ruby/object:Gem::Dependency
62
89
  name: rubocop-jekyll
63
90
  requirement: !ruby/object:Gem::Requirement
@@ -72,7 +99,90 @@ dependencies:
72
99
  - - "~>"
73
100
  - !ruby/object:Gem::Version
74
101
  version: '0.10'
75
- description:
102
+ - !ruby/object:Gem::Dependency
103
+ name: rubocop-performance
104
+ requirement: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - "~>"
107
+ - !ruby/object:Gem::Version
108
+ version: '1.5'
109
+ type: :development
110
+ prerelease: false
111
+ version_requirements: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - "~>"
114
+ - !ruby/object:Gem::Version
115
+ version: '1.5'
116
+ - !ruby/object:Gem::Dependency
117
+ name: rubocop-rspec
118
+ requirement: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - "~>"
121
+ - !ruby/object:Gem::Version
122
+ version: '3.0'
123
+ type: :development
124
+ prerelease: false
125
+ version_requirements: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - "~>"
128
+ - !ruby/object:Gem::Version
129
+ version: '3.0'
130
+ - !ruby/object:Gem::Dependency
131
+ name: base64
132
+ requirement: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - ">="
135
+ - !ruby/object:Gem::Version
136
+ version: '0'
137
+ type: :development
138
+ prerelease: false
139
+ version_requirements: !ruby/object:Gem::Requirement
140
+ requirements:
141
+ - - ">="
142
+ - !ruby/object:Gem::Version
143
+ version: '0'
144
+ - !ruby/object:Gem::Dependency
145
+ name: benchmark
146
+ requirement: !ruby/object:Gem::Requirement
147
+ requirements:
148
+ - - ">="
149
+ - !ruby/object:Gem::Version
150
+ version: '0'
151
+ type: :development
152
+ prerelease: false
153
+ version_requirements: !ruby/object:Gem::Requirement
154
+ requirements:
155
+ - - ">="
156
+ - !ruby/object:Gem::Version
157
+ version: '0'
158
+ - !ruby/object:Gem::Dependency
159
+ name: ostruct
160
+ requirement: !ruby/object:Gem::Requirement
161
+ requirements:
162
+ - - ">="
163
+ - !ruby/object:Gem::Version
164
+ version: '0'
165
+ type: :development
166
+ prerelease: false
167
+ version_requirements: !ruby/object:Gem::Requirement
168
+ requirements:
169
+ - - ">="
170
+ - !ruby/object:Gem::Version
171
+ version: '0'
172
+ - !ruby/object:Gem::Dependency
173
+ name: tsort
174
+ requirement: !ruby/object:Gem::Requirement
175
+ requirements:
176
+ - - ">="
177
+ - !ruby/object:Gem::Version
178
+ version: '0'
179
+ type: :development
180
+ prerelease: false
181
+ version_requirements: !ruby/object:Gem::Requirement
182
+ requirements:
183
+ - - ">="
184
+ - !ruby/object:Gem::Version
185
+ version: '0'
76
186
  email:
77
187
  - ben.balter@github.com
78
188
  executables: []
@@ -81,13 +191,14 @@ extra_rdoc_files: []
81
191
  files:
82
192
  - lib/jekyll-relative-links.rb
83
193
  - lib/jekyll-relative-links/context.rb
194
+ - lib/jekyll-relative-links/filter.rb
84
195
  - lib/jekyll-relative-links/generator.rb
196
+ - lib/jekyll-relative-links/hooks.rb
85
197
  - lib/jekyll-relative-links/version.rb
86
198
  homepage: https://github.com/benbalter/jekyll-relative-links
87
199
  licenses:
88
200
  - MIT
89
201
  metadata: {}
90
- post_install_message:
91
202
  rdoc_options: []
92
203
  require_paths:
93
204
  - lib
@@ -102,8 +213,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
102
213
  - !ruby/object:Gem::Version
103
214
  version: '0'
104
215
  requirements: []
105
- rubygems_version: 3.0.6
106
- signing_key:
216
+ rubygems_version: 4.0.16
107
217
  specification_version: 4
108
218
  summary: A Jekyll plugin to convert relative links to markdown files to their rendered
109
219
  equivalents.