jekyll_href 1.2.1 → 1.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +10 -3
- data/CHANGELOG.md +6 -0
- data/README.md +93 -8
- data/jekyll_href.gemspec +2 -1
- data/lib/hash_array.rb +32 -0
- data/lib/href_summary_tag.rb +79 -0
- data/lib/href_tag.rb +214 -0
- data/lib/jekyll_href/version.rb +1 -1
- data/lib/jekyll_href.rb +6 -165
- data/spec/hash_array_spec.rb +43 -0
- data/spec/href_spec.rb +44 -98
- data/spec/spec_helper.rb +68 -3
- data/spec/status_persistence.txt +27 -13
- metadata +29 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9e9e6357f4c5f4d4dd7815aab9142ab5dadfbc48b3ba719fdc6b1cd70265d3d3
|
4
|
+
data.tar.gz: '068d3c6821f1f8578fee4331179be452ad50fdfd620cc990a0dbdb1359f605cc'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d4411b3c9cfad7062eb75206f487e6e1a5589874479ae09815d044177069fd567b069875b9fabd4018dc9aafed9dc5dcc656354917c90935311ee958b6c1d5c2
|
7
|
+
data.tar.gz: abc4e78a0745ab9f455c5e1a1f85d0a41aa85c242f155c8d064503d5682df69806ef98c06c838833d37b1d3468713d5a21e798b7bf33570d48e2e27f76450fb8
|
data/.rubocop.yml
CHANGED
@@ -25,8 +25,7 @@ Gemspec/RequireMFA:
|
|
25
25
|
|
26
26
|
Layout/HashAlignment:
|
27
27
|
EnforcedColonStyle: table
|
28
|
-
|
29
|
-
- jekyll_href.gemspec
|
28
|
+
EnforcedHashRocketStyle: table
|
30
29
|
|
31
30
|
Layout/InitialIndentation:
|
32
31
|
Exclude:
|
@@ -34,6 +33,8 @@ Layout/InitialIndentation:
|
|
34
33
|
|
35
34
|
Layout/LineLength:
|
36
35
|
Max: 150
|
36
|
+
Exclude:
|
37
|
+
- spec/**/*
|
37
38
|
|
38
39
|
Layout/MultilineMethodCallIndentation:
|
39
40
|
Enabled: false
|
@@ -70,11 +71,17 @@ Naming/FileName:
|
|
70
71
|
- Rakefile
|
71
72
|
|
72
73
|
RSpec/ExampleLength:
|
73
|
-
Max:
|
74
|
+
Max: 40
|
75
|
+
|
76
|
+
RSpec/FilePath:
|
77
|
+
Enabled: false
|
74
78
|
|
75
79
|
RSpec/MultipleExpectations:
|
76
80
|
Max: 15
|
77
81
|
|
82
|
+
RSpec/MultipleMemoizedHelpers:
|
83
|
+
Max: 20
|
84
|
+
|
78
85
|
Style/CommandLiteral:
|
79
86
|
Enabled: false
|
80
87
|
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
## 1.2.2 / 2023-03-25
|
2
|
+
* Added **References** capability:
|
3
|
+
* Added `summary_exclude` keyword option to `href` tag.
|
4
|
+
* Added `href_summary` tag.
|
5
|
+
* If a URL appears in more than one `href` with different `follow` values a warning is logged.
|
6
|
+
|
1
7
|
## 1.2.1 / 2023-03-21
|
2
8
|
* Added `shy` and `wbr` options.
|
3
9
|
|
data/README.md
CHANGED
@@ -35,7 +35,7 @@ plugin-vars:
|
|
35
35
|
|
36
36
|
## Syntax 1 (requires `url` does not have embedded spaces)
|
37
37
|
```
|
38
|
-
{% href [match | [follow] [blank|notarget]] url text to display %}
|
38
|
+
{% href [match | [follow] [blank|notarget] [summary_exclude]] url text to display %}
|
39
39
|
```
|
40
40
|
1. The url must be a single token, without embedded spaces.
|
41
41
|
2. The url need not be enclosed in quotes.
|
@@ -45,11 +45,8 @@ plugin-vars:
|
|
45
45
|
## Syntax 2 (always works)
|
46
46
|
This syntax is recommended when the URL contains a colon (:).
|
47
47
|
```
|
48
|
-
{% href [match | [follow] [blank|notarget]]
|
48
|
+
{% href [match | [follow] [blank|notarget]] [summary_exclude]
|
49
49
|
url="http://link.com with space.html" some text %}
|
50
|
-
|
51
|
-
{% href [match | [follow] [blank|notarget]]
|
52
|
-
url='http://link.com with space.html' some text %}
|
53
50
|
```
|
54
51
|
1. Each of the above examples contain an embedded newline, which is legal.
|
55
52
|
2. The url must be enclosed by either single or double quotes.
|
@@ -58,7 +55,7 @@ This syntax is recommended when the URL contains a colon (:).
|
|
58
55
|
|
59
56
|
## Syntax 3 (implicit URL)
|
60
57
|
```
|
61
|
-
{% href [match | [follow] [blank|notarget]] [shy|wbr] www.domain.com %}
|
58
|
+
{% href [match | [follow] [blank|notarget] [summary_exclude]] [shy|wbr] www.domain.com %}
|
62
59
|
```
|
63
60
|
The URI provided, for example `www.domain.com`,
|
64
61
|
is used to form the URL by prepending `https://`,
|
@@ -117,7 +114,7 @@ Expands to:
|
|
117
114
|
```
|
118
115
|
|
119
116
|
### `shy`
|
120
|
-
`shy` is only applicable for syntax 3 (implicit URL).
|
117
|
+
The `shy` keyword option is only applicable for syntax 3 (implicit URL).
|
121
118
|
This option causes displayed urls to have an [`­`](https://developer.mozilla.org/en-US/docs/Web/CSS/hyphens) inserted after each slash (/).
|
122
119
|
If both `shy` and `wbr` are specified, `wbr` prevails.
|
123
120
|
|
@@ -130,8 +127,21 @@ Expands to:
|
|
130
127
|
<a href="https://mslinn.com/path/to/page.html" rel="nofollow" target="_blank">mslinn.com/­path/­to/­page.html</a>
|
131
128
|
```
|
132
129
|
|
130
|
+
### `summary`
|
131
|
+
The `summary` name/value option provides an override for the linked text in the **References** section
|
132
|
+
generated by the `{% href_summary %}` tag.
|
133
|
+
|
134
|
+
|
135
|
+
### `summary_exclude`
|
136
|
+
The `summary_exclude` keyword option prevents this `href` tag from appearing in the summary
|
137
|
+
produced by the [<code>href_summary</code> tag](#href_summary).
|
138
|
+
You probably want all of your menu items (whose links are generated by the `href` tag) to have this keyword option.
|
139
|
+
|
140
|
+
`mailto:` links are always excluded, so there is no need to use this keyword option for those types of links.
|
141
|
+
|
142
|
+
|
133
143
|
### `wbr`
|
134
|
-
`wbr` is only applicable for syntax 3 (implicit URL).
|
144
|
+
The `wbr` keyword option is only applicable for syntax 3 (implicit URL).
|
135
145
|
It add [line break opportunites](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/wbr).
|
136
146
|
This option causes displayed urls to have an `<wbr>` inserted after each slash (/).
|
137
147
|
If both `shy` and `wbr` are specified, `wbr` prevails.
|
@@ -185,6 +195,81 @@ Expands to:
|
|
185
195
|
Substitutions are only made to the URL, not to the linked text.
|
186
196
|
|
187
197
|
|
198
|
+
## References Generation
|
199
|
+
The `href` usages on each page can be summarized at the bottom of the pages in a **References** section.
|
200
|
+
Links are presented in the summary in the order they appear in the page.
|
201
|
+
|
202
|
+
The summary is produced by the `href_summary` tag.
|
203
|
+
Usage is:
|
204
|
+
|
205
|
+
```html
|
206
|
+
{% href_summary [options] %}
|
207
|
+
```
|
208
|
+
|
209
|
+
`Href` tag options are used to generate the summary links,
|
210
|
+
just as they were in the text above the **References** summary section.
|
211
|
+
The only exception is the `summary` option, which overrides the linked text.
|
212
|
+
|
213
|
+
If more than one `href` tag specifies a URL,
|
214
|
+
the first one that appears in the page sets the value of the linked text.
|
215
|
+
|
216
|
+
If a URL appears in more than one `href` with different `follow` values, a warning is logged.
|
217
|
+
|
218
|
+
|
219
|
+
### Included `href` Tags
|
220
|
+
The following `href` tags are included in the summary:
|
221
|
+
|
222
|
+
- Those with links that start with `http` are always included.
|
223
|
+
- Those with [relative links](https://www.w3.org/TR/WD-html40-970917/htmlweb.html#h-5.1.2),
|
224
|
+
and have the `include_local` keyword option.
|
225
|
+
|
226
|
+
### Excluded `href` Tags
|
227
|
+
The following `href` tags are excluded from the summary:
|
228
|
+
|
229
|
+
- Those with links that start with `mailto:`.
|
230
|
+
- Those having the `summary_exclude` keyword option.
|
231
|
+
|
232
|
+
|
233
|
+
### Example
|
234
|
+
Given these `href` and `href_summary` usages in a web page:
|
235
|
+
|
236
|
+
```html
|
237
|
+
{% href https://rubygems.org RubyGems.org %}
|
238
|
+
{% href summary="Mothership" https://jekyllrb.com/ Jekyll %}
|
239
|
+
{% href summary="Mike Slinn" mslinn.com %}
|
240
|
+
{% href https://mslinn.com Mike Slinn %}
|
241
|
+
{% href summary="Front page of this website" / Front page %}
|
242
|
+
|
243
|
+
{% href_summary attribution include_local %}
|
244
|
+
```
|
245
|
+
|
246
|
+
Then the generated HTML looks like the following:
|
247
|
+
|
248
|
+
```html
|
249
|
+
<h2 id="reference">References</h2>
|
250
|
+
<ol>
|
251
|
+
<li><a href='https://rubygems.org' rel='nofollow' target='_blank'>RubyGems.org</a></li>
|
252
|
+
<li><a href='https://jekyllrb.com/' rel='nofollow' target='_blank'>Mothership</a></li>
|
253
|
+
<li><a href='https://mslinn.com/' rel='nofollow' target='_blank'><code>mslinn.com</code></a></li>
|
254
|
+
</ol>
|
255
|
+
|
256
|
+
<h2 id="local_reference">Local References</h2>
|
257
|
+
<ol>
|
258
|
+
<li><a href='/'>Front page of this website</a></li>
|
259
|
+
</ol>
|
260
|
+
|
261
|
+
<div id="jps_attribute_735866" class="jps_attribute">
|
262
|
+
<div>
|
263
|
+
<a href="https://www.mslinn.com/jekyll/3000-jekyll-plugins.html#href" target="_blank" rel="nofollow">
|
264
|
+
Generated by the jekyll_href v1.2.2 Jekyll plugin, written by Mike Slinn 2023-04-13.
|
265
|
+
</a>
|
266
|
+
</div>
|
267
|
+
</div>
|
268
|
+
```
|
269
|
+
|
270
|
+
You can read about the `attribution` option [here](https://www.mslinn.com/jekyll/10200-jekyll-plugin-support.html#attribution).
|
271
|
+
|
272
|
+
|
188
273
|
## Additional Information
|
189
274
|
More information is available on my website about
|
190
275
|
[my Jekyll plugins](https://www.mslinn.com/blog/2020/10/03/jekyll-plugins.html).
|
data/jekyll_href.gemspec
CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
|
|
10
10
|
END_OF_DESC
|
11
11
|
spec.email = ['mslinn@mslinn.com']
|
12
12
|
spec.files = Dir['.rubocop.yml', 'LICENSE.*', 'Rakefile', '{lib,spec}/**/*', '*.gemspec', '*.md']
|
13
|
-
spec.homepage = 'https://www.mslinn.com/
|
13
|
+
spec.homepage = 'https://www.mslinn.com/jekyll/3000-jekyll-plugins.html#href'
|
14
14
|
spec.license = 'MIT'
|
15
15
|
spec.metadata = {
|
16
16
|
'allowed_push_host' => 'https://rubygems.org',
|
@@ -33,4 +33,5 @@ Gem::Specification.new do |spec|
|
|
33
33
|
|
34
34
|
spec.add_dependency 'jekyll', '>= 3.5.0'
|
35
35
|
spec.add_dependency 'jekyll_all_collections', '~> 0.3.0', '>= 0.3.1'
|
36
|
+
spec.add_dependency 'jekyll_plugin_support', '~> 0.6.0', '>= 0.6.1'
|
36
37
|
end
|
data/lib/hash_array.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
module HashArray
|
2
|
+
def reset
|
3
|
+
@local_hrefs = {}
|
4
|
+
@global_hrefs = {}
|
5
|
+
end
|
6
|
+
|
7
|
+
def add_link_for_page(href, hash)
|
8
|
+
enclosing_page = href.path
|
9
|
+
hash[enclosing_page] = [] if hash[enclosing_page].nil?
|
10
|
+
pre_existing = hash[enclosing_page].find { |h| h.link_save == href.link_save }
|
11
|
+
if pre_existing
|
12
|
+
if pre_existing.follow != href.follow
|
13
|
+
@logger.warn "HRef tags for '#{href.link}' have inconsistent 'follow' keyword options on line #{href.line_number} of #{enclosing_page}"
|
14
|
+
end
|
15
|
+
else
|
16
|
+
hash[enclosing_page] << href unless href.summary_exclude
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def add_local_link_for_page(href)
|
21
|
+
add_link_for_page(href, HashArray.instance_variable_get(:@local_hrefs))
|
22
|
+
end
|
23
|
+
|
24
|
+
def add_global_link_for_page(href)
|
25
|
+
add_link_for_page(href, HashArray.instance_variable_get(:@global_hrefs))
|
26
|
+
end
|
27
|
+
|
28
|
+
module_function :add_link_for_page, :add_local_link_for_page, :add_global_link_for_page, :reset
|
29
|
+
public :add_local_link_for_page, :add_global_link_for_page, :reset
|
30
|
+
|
31
|
+
reset
|
32
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'jekyll_plugin_logger'
|
2
|
+
require 'jekyll_plugin_support'
|
3
|
+
require_relative 'jekyll_href/version'
|
4
|
+
|
5
|
+
module HrefSummaryTag
|
6
|
+
class HrefSummary < JekyllSupport::JekyllTag # rubocop:disable Metrics/ClassLength
|
7
|
+
include JekyllHrefVersion
|
8
|
+
|
9
|
+
# Class instance variables accumulate hrefs across invocations.
|
10
|
+
# These are hashes of arrays;
|
11
|
+
# the hash keys are page paths (strings) and the hash values are arrays of HRefTags.
|
12
|
+
# {
|
13
|
+
# 'path/to/page1.html': [ HRefTag1, HRefTag2 ],
|
14
|
+
# 'path/to/page2.html': [ HRefTag3, HRefTag4 ],
|
15
|
+
# }
|
16
|
+
@hrefs = {}
|
17
|
+
@hrefs_local = {}
|
18
|
+
|
19
|
+
class << self
|
20
|
+
attr_accessor :hrefs, :hrefs_local
|
21
|
+
end
|
22
|
+
|
23
|
+
include JekyllHrefVersion
|
24
|
+
|
25
|
+
# Method prescribed by the Jekyll plugin lifecycle.
|
26
|
+
# @param liquid_context [Liquid::Context]
|
27
|
+
# @return [String]
|
28
|
+
def render_impl
|
29
|
+
@helper.gem_file __FILE__ # Enables attribution
|
30
|
+
@include_local = @helper.parameter_specified? 'include_local'
|
31
|
+
global_refs = render_global_refs
|
32
|
+
local_refs = render_local_refs
|
33
|
+
have_refs = !(global_refs + local_refs).empty?
|
34
|
+
<<~END_RENDER
|
35
|
+
#{global_refs}
|
36
|
+
#{local_refs}
|
37
|
+
#{@helper.attribute if @helper.attribution && have_refs}
|
38
|
+
END_RENDER
|
39
|
+
end
|
40
|
+
|
41
|
+
def render_global_refs
|
42
|
+
hrefs = HashArray.instance_variable_get(:@global_hrefs)
|
43
|
+
path = @page['path']
|
44
|
+
entries = hrefs[path]&.select { |h| h.path == path }
|
45
|
+
return '' if entries.nil? || entries.empty?
|
46
|
+
|
47
|
+
summaries = entries.map { |href| "<li>#{href.summary_href}</li>" }
|
48
|
+
|
49
|
+
<<~END_RENDER
|
50
|
+
<h2 id="reference">References</h2>
|
51
|
+
<ol>
|
52
|
+
#{summaries.join "\n "}
|
53
|
+
</ol>
|
54
|
+
END_RENDER
|
55
|
+
rescue StandardError => e
|
56
|
+
@logger.error { "#{self.class} died with a #{e.full_message}" }
|
57
|
+
exit 1
|
58
|
+
end
|
59
|
+
|
60
|
+
def render_local_refs
|
61
|
+
return '' unless @include_local
|
62
|
+
|
63
|
+
hrefs = HashArray.instance_variable_get(:@local_hrefs)
|
64
|
+
path = @page['path']
|
65
|
+
entries = hrefs[path]&.select { |h| h.path == path }
|
66
|
+
return '' if entries.nil? || entries.empty?
|
67
|
+
|
68
|
+
summary = entries.map { |href| "<li>#{href.summary_href}</li>" }
|
69
|
+
<<~END_RENDER
|
70
|
+
<h2 id="local_reference">Local References</h2>
|
71
|
+
<ol>
|
72
|
+
#{summary.join("\n ")}
|
73
|
+
</ol>
|
74
|
+
END_RENDER
|
75
|
+
end
|
76
|
+
|
77
|
+
JekyllPluginHelper.register(self, 'href_summary')
|
78
|
+
end
|
79
|
+
end
|
data/lib/href_tag.rb
ADDED
@@ -0,0 +1,214 @@
|
|
1
|
+
require 'jekyll_all_collections'
|
2
|
+
require 'jekyll_plugin_logger'
|
3
|
+
require 'jekyll_plugin_support'
|
4
|
+
require 'liquid'
|
5
|
+
require_relative 'jekyll_href/version'
|
6
|
+
require_relative 'hash_array'
|
7
|
+
|
8
|
+
# @author Copyright 2020 Michael Slinn
|
9
|
+
# @license SPDX-License-Identifier: Apache-2.0
|
10
|
+
# Generates an href.
|
11
|
+
|
12
|
+
module HrefTag
|
13
|
+
MiniHref = Struct.new(:follow, :html, :link, :line_number, :link_save, :path, :summary_exclude, :summary_href, keyword_init: true)
|
14
|
+
|
15
|
+
# Implements href Jekyll tag
|
16
|
+
class HrefTag < JekyllSupport::JekyllTag # rubocop:disable Metrics/ClassLength
|
17
|
+
attr_reader :follow, :helper, :line_number, :link_save, :match, :page, :path, :site,
|
18
|
+
:summary, :summary_exclude, :summary_href, :target, :text, :url
|
19
|
+
attr_accessor :link
|
20
|
+
|
21
|
+
include JekyllHrefVersion
|
22
|
+
include HashArray
|
23
|
+
include Comparable
|
24
|
+
|
25
|
+
def <=>(other)
|
26
|
+
return nil unless other.is_a?(self.class)
|
27
|
+
|
28
|
+
[follow, match, path, target, text] <=> [other.follow, other.match, other.path, other.target, other.text]
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_s
|
32
|
+
"On line #{line_number} of #{path}: #{follow} #{match} #{target} #{link} => '#{text}'"
|
33
|
+
end
|
34
|
+
|
35
|
+
# Method prescribed by the Jekyll plugin lifecycle.
|
36
|
+
# @param liquid_context [Liquid::Context]
|
37
|
+
# @return [String]
|
38
|
+
def render_impl
|
39
|
+
globals_initial
|
40
|
+
linkk = compute_linkk
|
41
|
+
linkk = replace_vars(linkk)
|
42
|
+
linkk.delete_prefix('./') # normalize relative links
|
43
|
+
@url = linkk if @url
|
44
|
+
@link_save = linkk
|
45
|
+
@helper_save = @helper.clone
|
46
|
+
globals_update(@helper.argv, linkk) # Sets @link and @text, might clear @follow and @target
|
47
|
+
handle_match if @match
|
48
|
+
save_summary
|
49
|
+
"<a href='#{@link}'#{@target}#{@follow}>#{@text}</a>"
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def save_summary
|
55
|
+
return if @summary_exclude || @link_save.start_with?('mailto:') || @link_save.start_with?('#')
|
56
|
+
|
57
|
+
@summary = @summary.to_s.empty? ? @text : @summary.to_s
|
58
|
+
@summary = @summary[0].upcase + @summary[1..]
|
59
|
+
@summary_href = "<a href='#{@link_save}'#{@target}#{@follow}>#{@summary}</a>"
|
60
|
+
mini_href = MiniHref.new(
|
61
|
+
follow: @follow,
|
62
|
+
html: @summary_href,
|
63
|
+
line_number: @line_number,
|
64
|
+
link: @link_save,
|
65
|
+
link_save: @link_save,
|
66
|
+
path: @path,
|
67
|
+
summary_exclude: @summary_exclude,
|
68
|
+
summary_href: @summary_href
|
69
|
+
)
|
70
|
+
if @link_save.start_with? 'http'
|
71
|
+
add_global_link_for_page mini_href
|
72
|
+
else
|
73
|
+
add_local_link_for_page mini_href
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# Does not look at or compute @link
|
78
|
+
def compute_linkk
|
79
|
+
return @link if @link
|
80
|
+
|
81
|
+
linkk = @url
|
82
|
+
if linkk.nil? || !linkk
|
83
|
+
linkk = @helper.argv&.shift
|
84
|
+
@helper.params&.shift
|
85
|
+
@helper.keys_values&.delete(linkk)
|
86
|
+
dump_linkk_relations(linkk) if linkk.nil?
|
87
|
+
elsif @url.to_s.empty?
|
88
|
+
dump_linkk_relations(linkk)
|
89
|
+
end
|
90
|
+
linkk
|
91
|
+
end
|
92
|
+
|
93
|
+
def dump_linkk_relations(linkk)
|
94
|
+
msg = <<~END_MESSAGE
|
95
|
+
jekyll_href error: no url was provided on #{@path}:#{@line_number}.
|
96
|
+
@helper.markup=#{@helper.markup}
|
97
|
+
@helper.argv='#{@helper.argv}'
|
98
|
+
linkk='#{linkk}'
|
99
|
+
@match='#{@match}'
|
100
|
+
@url='#{@url}'
|
101
|
+
@follow='#{@follow}
|
102
|
+
@target='#{@target}'
|
103
|
+
END_MESSAGE
|
104
|
+
abort msg.red
|
105
|
+
end
|
106
|
+
|
107
|
+
# Sets @follow, @helper, @match, @path, @shy, @target, @url, @wbr
|
108
|
+
def globals_initial
|
109
|
+
@path = @page['path']
|
110
|
+
AllCollectionsHooks.compute(@site)
|
111
|
+
|
112
|
+
@follow = @helper.parameter_specified?('follow') ? '' : " rel='nofollow'"
|
113
|
+
@match = @helper.parameter_specified? 'match'
|
114
|
+
@blank = @helper.parameter_specified? 'blank'
|
115
|
+
@summary_exclude = @helper.parameter_specified? 'summary_exclude'
|
116
|
+
@shy = @helper.parameter_specified? 'shy'
|
117
|
+
@summary = @helper.parameter_specified? 'summary'
|
118
|
+
@target = @blank ? " target='_blank'" : nil
|
119
|
+
@target ||= @helper.parameter_specified?('notarget') ? '' : " target='_blank'"
|
120
|
+
@url = @helper.parameter_specified? 'url'
|
121
|
+
@wbr = @helper.parameter_specified? 'wbr'
|
122
|
+
end
|
123
|
+
|
124
|
+
# Might set @follow, @linkk, @target, and @text
|
125
|
+
def globals_update(tokens, linkk)
|
126
|
+
if linkk.start_with? 'mailto:'
|
127
|
+
@link = linkk
|
128
|
+
@target = @follow = ''
|
129
|
+
@text = @helper.argv.join(' ')
|
130
|
+
if @text.empty?
|
131
|
+
text = linkk.delete_prefix('mailto:')
|
132
|
+
@text = "<code>#{text}</code>"
|
133
|
+
end
|
134
|
+
return
|
135
|
+
else
|
136
|
+
@text = tokens.join(' ').strip
|
137
|
+
if @text.to_s.empty?
|
138
|
+
text = linkk
|
139
|
+
text = linkk.gsub('/', '/­') if @shy
|
140
|
+
text = linkk.gsub('/', '/<wbr>') if @wbr
|
141
|
+
@text = "<code>#{text}</code>"
|
142
|
+
@link = linkk.start_with?('http') ? linkk : "https://#{linkk}"
|
143
|
+
else
|
144
|
+
@link = if @shy
|
145
|
+
linkk.gsub('/', '/­')
|
146
|
+
elsif @wbr
|
147
|
+
linkk.gsub('/', '/<wbr>')
|
148
|
+
else
|
149
|
+
linkk
|
150
|
+
end
|
151
|
+
end
|
152
|
+
@link_save = @link
|
153
|
+
end
|
154
|
+
|
155
|
+
return if @link.start_with? 'http'
|
156
|
+
|
157
|
+
@follow = ''
|
158
|
+
@target = '' unless @blank
|
159
|
+
end
|
160
|
+
|
161
|
+
def handle_match
|
162
|
+
match_post
|
163
|
+
@follow = ''
|
164
|
+
@target = '' unless @blank
|
165
|
+
end
|
166
|
+
|
167
|
+
# Might set @link and @text
|
168
|
+
def match_post
|
169
|
+
config = @site.config['href']
|
170
|
+
@die_if_nomatch = !config.nil? && config['nomatch'] && config['nomatch'] == 'fatal'
|
171
|
+
@path, @fragment = @link.split('#')
|
172
|
+
|
173
|
+
@logger.debug do
|
174
|
+
<<~END_DEBUG
|
175
|
+
@link=#{@link}
|
176
|
+
@site.posts.docs[0].url = #{@site.posts.docs[0].url}
|
177
|
+
@site.posts.docs[0].path = #{@site.posts.docs[0].path}
|
178
|
+
END_DEBUG
|
179
|
+
end
|
180
|
+
|
181
|
+
all_urls = @site.all_collections.map(&:url)
|
182
|
+
compute_link_and_text(all_urls)
|
183
|
+
end
|
184
|
+
|
185
|
+
def compute_link_and_text(all_urls)
|
186
|
+
url_matches = all_urls.select { |url| url&.include? @path }
|
187
|
+
case url_matches.length
|
188
|
+
when 0
|
189
|
+
abort "href error: No url matches '#{@link}'" if @die_if_nomatch
|
190
|
+
@link_save = @link = '#'
|
191
|
+
@text = "<i>#{@link} is not available</i>"
|
192
|
+
when 1
|
193
|
+
@link = url_matches.first
|
194
|
+
@link = "#{@link}##{@fragment}" if @fragment
|
195
|
+
@link_save = @link
|
196
|
+
else
|
197
|
+
abort "Error: More than one url matched '#{@path}': #{url_matches.join(', ')}"
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
# Replace names in plugin-vars with values
|
202
|
+
def replace_vars(text)
|
203
|
+
variables = @site.config['plugin-vars']
|
204
|
+
return text unless variables
|
205
|
+
|
206
|
+
variables.each do |name, value|
|
207
|
+
text = text.gsub "{{#{name}}}", value
|
208
|
+
end
|
209
|
+
text
|
210
|
+
end
|
211
|
+
|
212
|
+
JekyllPluginHelper.register(self, 'href')
|
213
|
+
end
|
214
|
+
end
|
data/lib/jekyll_href/version.rb
CHANGED
data/lib/jekyll_href.rb
CHANGED
@@ -1,168 +1,9 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require 'jekyll_plugin_support'
|
4
|
-
require 'liquid'
|
5
|
-
require_relative 'jekyll_href/version'
|
1
|
+
require_relative 'href_tag'
|
2
|
+
require_relative 'href_summary_tag'
|
6
3
|
|
7
|
-
|
8
|
-
# @license SPDX-License-Identifier: Apache-2.0
|
9
|
-
# Generates an href.
|
4
|
+
HrefError = Class.new(Liquid::Error)
|
10
5
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
attr_accessor :link
|
15
|
-
|
16
|
-
include JekyllHrefVersion
|
17
|
-
|
18
|
-
# Method prescribed by the Jekyll plugin lifecycle.
|
19
|
-
# @param liquid_context [Liquid::Context]
|
20
|
-
# @return [String]
|
21
|
-
def render_impl
|
22
|
-
globals_initial
|
23
|
-
linkk = compute_linkk
|
24
|
-
linkk = replace_vars(linkk)
|
25
|
-
@link_save = linkk
|
26
|
-
@helper_save = @helper.clone
|
27
|
-
globals_update(@helper.argv, linkk) # Sets @link and @text, might clear @follow and @target
|
28
|
-
handle_match if @match
|
29
|
-
|
30
|
-
"<a href='#{@link}'#{@target}#{@follow}>#{@text}</a>"
|
31
|
-
end
|
32
|
-
|
33
|
-
private
|
34
|
-
|
35
|
-
# Does not look at or compute @link
|
36
|
-
def compute_linkk
|
37
|
-
return @link if @link
|
38
|
-
|
39
|
-
linkk = @url
|
40
|
-
if linkk.nil? || !linkk
|
41
|
-
linkk = @helper.argv&.shift
|
42
|
-
@helper.params&.shift
|
43
|
-
@helper.keys_values&.delete(linkk)
|
44
|
-
dump_linkk_relations(linkk) if linkk.nil?
|
45
|
-
elsif @url.to_s.empty?
|
46
|
-
dump_linkk_relations(linkk)
|
47
|
-
end
|
48
|
-
linkk
|
49
|
-
end
|
50
|
-
|
51
|
-
def dump_linkk_relations(linkk)
|
52
|
-
msg = <<~END_MESSAGE
|
53
|
-
jekyll_href error: no url was provided on #{@path}:#{@line_number}.
|
54
|
-
@helper.markup=#{@helper.markup}
|
55
|
-
@helper.argv='#{@helper.argv}'
|
56
|
-
linkk='#{linkk}'
|
57
|
-
@match='#{@match}'
|
58
|
-
@url='#{@url}'
|
59
|
-
@follow='#{@follow}
|
60
|
-
@target='#{@target}'
|
61
|
-
END_MESSAGE
|
62
|
-
abort msg.red
|
63
|
-
end
|
64
|
-
|
65
|
-
# Sets @follow, @helper, @match, @path, @shy, @target, @url, @wbr
|
66
|
-
def globals_initial
|
67
|
-
@path = @page['path']
|
68
|
-
AllCollectionsHooks.compute(@site)
|
69
|
-
|
70
|
-
@follow = @helper.parameter_specified?('follow') ? '' : " rel='nofollow'"
|
71
|
-
@match = @helper.parameter_specified?('match')
|
72
|
-
@blank = @helper.parameter_specified?('blank')
|
73
|
-
@shy = @helper.parameter_specified?('shy')
|
74
|
-
@target = @blank ? " target='_blank'" : nil
|
75
|
-
@target ||= @helper.parameter_specified?('notarget') ? '' : " target='_blank'"
|
76
|
-
@url = @helper.parameter_specified?('url')
|
77
|
-
@wbr = @helper.parameter_specified?('wbr')
|
78
|
-
end
|
79
|
-
|
80
|
-
# Might set @follow, @linkk, @target, and @text
|
81
|
-
def globals_update(tokens, linkk)
|
82
|
-
if linkk.start_with? 'mailto:'
|
83
|
-
@link = linkk
|
84
|
-
@target = @follow = ''
|
85
|
-
@text = @helper.argv.join(' ')
|
86
|
-
if @text.empty?
|
87
|
-
text = linkk.delete_prefix('mailto:')
|
88
|
-
@text = "<code>#{text}</code>"
|
89
|
-
end
|
90
|
-
return
|
91
|
-
else
|
92
|
-
@text = tokens.join(' ').strip
|
93
|
-
if @text.to_s.empty?
|
94
|
-
text = linkk
|
95
|
-
text = linkk.gsub('/', '/­') if @shy
|
96
|
-
text = linkk.gsub('/', '/<wbr>') if @wbr
|
97
|
-
@text = "<code>#{text}</code>"
|
98
|
-
@link = "https://#{linkk}"
|
99
|
-
else
|
100
|
-
@link = if @shy
|
101
|
-
linkk.gsub('/', '/­')
|
102
|
-
elsif @wbr
|
103
|
-
linkk.gsub('/', '/<wbr>')
|
104
|
-
else
|
105
|
-
linkk
|
106
|
-
end
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
return if @link.start_with? 'http'
|
111
|
-
|
112
|
-
@follow = ''
|
113
|
-
@target = '' unless @blank
|
114
|
-
end
|
115
|
-
|
116
|
-
def handle_match
|
117
|
-
match_post
|
118
|
-
@follow = ''
|
119
|
-
@target = '' unless @blank
|
120
|
-
end
|
121
|
-
|
122
|
-
# Might set @link and @text
|
123
|
-
def match_post
|
124
|
-
config = @site.config['href']
|
125
|
-
@die_if_nomatch = !config.nil? && config['nomatch'] && config['nomatch'] == 'fatal'
|
126
|
-
@path, @fragment = @link.split('#')
|
127
|
-
|
128
|
-
@logger.debug do
|
129
|
-
<<~END_DEBUG
|
130
|
-
@link=#{@link}
|
131
|
-
@site.posts.docs[0].url = #{@site.posts.docs[0].url}
|
132
|
-
@site.posts.docs[0].path = #{@site.posts.docs[0].path}
|
133
|
-
END_DEBUG
|
134
|
-
end
|
135
|
-
|
136
|
-
all_urls = @site.all_collections.map(&:url)
|
137
|
-
compute_link_and_text(all_urls)
|
138
|
-
end
|
139
|
-
|
140
|
-
def compute_link_and_text(all_urls)
|
141
|
-
url_matches = all_urls.select { |url| url&.include? @path }
|
142
|
-
case url_matches.length
|
143
|
-
when 0
|
144
|
-
abort "href error: No url matches '#{@link}'" if @die_if_nomatch
|
145
|
-
@link = '#'
|
146
|
-
@text = "<i>#{@link} is not available</i>"
|
147
|
-
when 1
|
148
|
-
@link = url_matches.first
|
149
|
-
@link = "#{@link}##{@fragment}" if @fragment
|
150
|
-
else
|
151
|
-
abort "Error: More than one url matched '#{@path}': #{url_matches.join(', ')}"
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
|
-
# Replace names in plugin-vars with values
|
156
|
-
def replace_vars(text)
|
157
|
-
variables = @site.config['plugin-vars']
|
158
|
-
return text unless variables
|
159
|
-
|
160
|
-
variables.each do |name, value|
|
161
|
-
text = text.gsub "{{#{name}}}", value
|
162
|
-
end
|
163
|
-
@logger.debug { "@link=#{@link}" }
|
164
|
-
text
|
165
|
-
end
|
166
|
-
|
167
|
-
JekyllPluginHelper.register(self, 'href')
|
6
|
+
module JekyllHrefModule
|
7
|
+
include HrefTag
|
8
|
+
include HrefSummaryTag
|
168
9
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module HashArraySpec
|
2
|
+
require_relative '../lib/hash_array'
|
3
|
+
|
4
|
+
RSpec.describe HashArray do
|
5
|
+
let(:logger) do
|
6
|
+
PluginMetaLogger.instance.new_logger(self, PluginMetaLogger.instance.config)
|
7
|
+
end
|
8
|
+
|
9
|
+
let(:parse_context) { TestParseContext.new }
|
10
|
+
|
11
|
+
[1, 2, 3, 4, 11, 22, 33, 44].each do |x|
|
12
|
+
let("href#{x}".to_sym) do
|
13
|
+
domain, where = if x.even?
|
14
|
+
['https://domain.com/', 'External']
|
15
|
+
else
|
16
|
+
['', 'Internal']
|
17
|
+
end
|
18
|
+
href = HrefTag::HrefTag.send(
|
19
|
+
:new,
|
20
|
+
'href',
|
21
|
+
+ "#{domain}path/page#{x}.html #{where} link text #{x}",
|
22
|
+
parse_context
|
23
|
+
)
|
24
|
+
href.render(TestLiquidContext.new)
|
25
|
+
href
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'accumulates arrays of href_tag' do
|
30
|
+
described_class.reset
|
31
|
+
[href1, href3, href11, href33].each { |x| described_class.add_local_link_for_page x }
|
32
|
+
[href2, href4, href22, href44].each { |x| described_class.add_global_link_for_page x }
|
33
|
+
|
34
|
+
local_hrefs = described_class.instance_variable_get :@local_hrefs
|
35
|
+
value = { 'index.html' => [href1, href3, href11, href33] }
|
36
|
+
expect(local_hrefs).to match_array(value)
|
37
|
+
|
38
|
+
global_hrefs = described_class.instance_variable_get :@global_hrefs
|
39
|
+
value = { 'index.html' => [href2, href4, href22, href44] }
|
40
|
+
expect(global_hrefs).to match_array(value)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/spec/href_spec.rb
CHANGED
@@ -1,49 +1,10 @@
|
|
1
|
-
require 'jekyll'
|
2
|
-
require 'jekyll_plugin_logger'
|
3
|
-
require 'yaml'
|
4
1
|
require_relative '../lib/jekyll_href'
|
5
2
|
|
6
|
-
Registers = Struct.new(:page, :site)
|
7
|
-
|
8
|
-
# Mock for Collections
|
9
|
-
class Collections
|
10
|
-
def values
|
11
|
-
[]
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
# Mock for Site
|
16
|
-
class SiteMock
|
17
|
-
attr_reader :config
|
18
|
-
|
19
|
-
def initialize
|
20
|
-
@config = YAML.safe_load(File.read('_config.yml'))
|
21
|
-
end
|
22
|
-
|
23
|
-
def collections
|
24
|
-
Collections.new
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
# Mock for Liquid::ParseContent
|
29
|
-
class TestParseContext < Liquid::ParseContext
|
30
|
-
attr_reader :line_number, :registers
|
31
|
-
|
32
|
-
def initialize
|
33
|
-
super
|
34
|
-
@line_number = 123
|
35
|
-
|
36
|
-
@registers = Registers.new(
|
37
|
-
{ 'path' => 'https://feeds.soundcloud.com/users/soundcloud:users:7143896/sounds.rss' },
|
38
|
-
SiteMock.new
|
39
|
-
)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
3
|
class MyTest
|
44
4
|
Dir.chdir 'demo'
|
5
|
+
HashArray.reset
|
45
6
|
|
46
|
-
RSpec.describe
|
7
|
+
RSpec.describe HrefTag::HrefTag do
|
47
8
|
let(:logger) do
|
48
9
|
PluginMetaLogger.instance.new_logger(self, PluginMetaLogger.instance.config)
|
49
10
|
end
|
@@ -58,209 +19,194 @@ class MyTest
|
|
58
19
|
)
|
59
20
|
end
|
60
21
|
|
61
|
-
it
|
22
|
+
it 'obtains internal link with blank' do
|
62
23
|
href = described_class.send(
|
63
24
|
:new,
|
64
25
|
'href',
|
65
|
-
+ 'blank
|
26
|
+
+ 'blank path/page.html internal link text',
|
66
27
|
parse_context
|
67
28
|
)
|
68
|
-
href.
|
69
|
-
linkk = href.send :compute_linkk
|
70
|
-
href.send(:globals_update, href.helper.argv, linkk)
|
29
|
+
href.render TestLiquidContext.new
|
71
30
|
expect(href.follow).to eq('')
|
72
|
-
expect(href.link).to eq('
|
31
|
+
expect(href.link).to eq('path/page.html')
|
73
32
|
expect(href.target).to eq(" target='_blank'")
|
74
33
|
expect(href.text).to eq('internal link text')
|
75
34
|
end
|
76
35
|
|
77
|
-
it
|
36
|
+
it 'obtains external link with text' do
|
78
37
|
href = described_class.send(
|
79
38
|
:new,
|
80
39
|
'href',
|
81
|
-
+ 'https://feeds.soundcloud.com/users/soundcloud:users:7143896/sounds.rss SoundCloud RSS Feed',
|
40
|
+
+ 'summary_exclude https://feeds.soundcloud.com/users/soundcloud:users:7143896/sounds.rss SoundCloud RSS Feed',
|
82
41
|
parse_context
|
83
42
|
)
|
84
|
-
href.
|
85
|
-
linkk = href.send(:compute_linkk)
|
86
|
-
href.send(:globals_update, href.helper.argv, linkk)
|
43
|
+
href.render TestLiquidContext.new
|
87
44
|
expect(href.follow).to eq(" rel='nofollow'")
|
88
45
|
expect(href.link).to eq('https://feeds.soundcloud.com/users/soundcloud:users:7143896/sounds.rss')
|
89
46
|
expect(href.target).to eq(" target='_blank'")
|
90
47
|
expect(href.text).to eq('SoundCloud RSS Feed')
|
91
48
|
end
|
92
49
|
|
93
|
-
it
|
50
|
+
it 'obtains external link using url parameter with text' do
|
94
51
|
href = described_class.send(
|
95
52
|
:new,
|
96
53
|
'href',
|
97
|
-
+ 'url="https://feeds.soundcloud.com/users/soundcloud:users:7143896/sounds.rss" SoundCloud RSS Feed',
|
54
|
+
+ 'summary_exclude url="https://feeds.soundcloud.com/users/soundcloud:users:7143896/sounds.rss" SoundCloud RSS Feed',
|
98
55
|
parse_context
|
99
56
|
)
|
100
|
-
href.
|
101
|
-
linkk = href.send(:compute_linkk)
|
102
|
-
href.send(:globals_update, href.helper.argv, linkk)
|
57
|
+
href.render TestLiquidContext.new
|
103
58
|
expect(href.follow).to eq(" rel='nofollow'")
|
104
59
|
expect(href.link).to eq('https://feeds.soundcloud.com/users/soundcloud:users:7143896/sounds.rss')
|
105
60
|
expect(href.target).to eq(" target='_blank'")
|
106
61
|
expect(href.text).to eq('SoundCloud RSS Feed')
|
107
62
|
end
|
108
63
|
|
109
|
-
it
|
64
|
+
it 'obtains external link without scheme or text' do
|
110
65
|
href = described_class.send(
|
111
66
|
:new,
|
112
67
|
'href',
|
113
68
|
+ 'super-fake-merger.com',
|
114
69
|
parse_context
|
115
70
|
)
|
116
|
-
href.
|
117
|
-
linkk = href.send(:compute_linkk)
|
118
|
-
href.send(:globals_update, href.helper.argv, linkk)
|
71
|
+
href.render TestLiquidContext.new
|
119
72
|
expect(href.follow).to eq(" rel='nofollow'")
|
120
73
|
expect(href.link).to eq('https://super-fake-merger.com')
|
121
74
|
expect(href.target).to eq(" target='_blank'")
|
122
75
|
expect(href.text).to eq('<code>super-fake-merger.com</code>')
|
123
76
|
end
|
124
77
|
|
125
|
-
it
|
78
|
+
it 'expands YAML hash with link text' do
|
126
79
|
href = described_class.send(
|
127
80
|
:new,
|
128
81
|
'href',
|
129
82
|
+ '{{github}}/diasks2/confidential_info_redactor <code>confidential_info_redactor</code>',
|
130
83
|
parse_context
|
131
84
|
)
|
132
|
-
href.
|
133
|
-
linkk = href.send(:compute_linkk)
|
134
|
-
linkk = href.send(:replace_vars, linkk)
|
135
|
-
href.send(:globals_update, href.helper.argv, linkk)
|
85
|
+
href.render TestLiquidContext.new
|
136
86
|
expect(href.follow).to eq(" rel='nofollow'")
|
137
87
|
expect(href.link).to eq('https://github.com/diasks2/confidential_info_redactor')
|
138
88
|
expect(href.target).to eq(" target='_blank'")
|
139
89
|
expect(href.text).to eq('<code>confidential_info_redactor</code>')
|
140
90
|
end
|
141
91
|
|
142
|
-
it
|
92
|
+
it 'obtains external link with follow' do
|
143
93
|
href = described_class.send(
|
144
94
|
:new,
|
145
95
|
'href',
|
146
96
|
+ 'follow https://www.mslinn.com Awesome',
|
147
97
|
parse_context
|
148
98
|
)
|
149
|
-
href.
|
150
|
-
linkk = href.send(:compute_linkk)
|
151
|
-
href.send(:globals_update, href.helper.argv, linkk)
|
99
|
+
href.render TestLiquidContext.new
|
152
100
|
expect(href.follow).to eq('')
|
153
101
|
expect(href.link).to eq('https://www.mslinn.com')
|
154
102
|
expect(href.target).to eq(" target='_blank'")
|
155
103
|
expect(href.text).to eq('Awesome')
|
156
104
|
end
|
157
105
|
|
158
|
-
it
|
106
|
+
it 'obtains external link with follow and notarget' do
|
159
107
|
href = described_class.send(
|
160
108
|
:new,
|
161
109
|
'href',
|
162
110
|
+ 'follow notarget https://www.mslinn.com Awesome',
|
163
111
|
parse_context
|
164
112
|
)
|
165
|
-
href.
|
166
|
-
linkk = href.send(:compute_linkk)
|
167
|
-
href.send(:globals_update, href.helper.argv, linkk)
|
113
|
+
href.render TestLiquidContext.new
|
168
114
|
expect(href.follow).to eq('')
|
169
115
|
expect(href.link).to eq('https://www.mslinn.com')
|
170
116
|
expect(href.target).to eq('')
|
171
117
|
expect(href.text).to eq('Awesome')
|
172
118
|
end
|
173
119
|
|
174
|
-
it
|
120
|
+
it 'obtains external link with blank' do
|
175
121
|
href = described_class.send(
|
176
122
|
:new,
|
177
123
|
'href',
|
178
124
|
+ 'blank https://www.mslinn.com Awesome',
|
179
125
|
parse_context
|
180
126
|
)
|
181
|
-
href.
|
182
|
-
linkk = href.send(:compute_linkk)
|
183
|
-
href.send(:globals_update, href.helper.argv, linkk)
|
127
|
+
href.render TestLiquidContext.new
|
184
128
|
expect(href.follow).to eq(" rel='nofollow'")
|
185
129
|
expect(href.link).to eq('https://www.mslinn.com')
|
186
130
|
expect(href.target).to eq(" target='_blank'")
|
187
131
|
expect(href.text).to eq('Awesome')
|
188
132
|
end
|
189
133
|
|
190
|
-
it
|
134
|
+
it 'implicitly computes external link from text' do
|
191
135
|
href = described_class.send(
|
192
136
|
:new,
|
193
137
|
'href',
|
194
138
|
+ 'www.mslinn.com',
|
195
139
|
parse_context
|
196
140
|
)
|
197
|
-
href.
|
198
|
-
linkk = href.send(:compute_linkk)
|
199
|
-
href.send(:globals_update, href.helper.argv, linkk)
|
141
|
+
href.render TestLiquidContext.new
|
200
142
|
expect(href.follow).to eq(" rel='nofollow'")
|
201
143
|
expect(href.link).to eq('https://www.mslinn.com')
|
202
144
|
expect(href.target).to eq(" target='_blank'")
|
203
145
|
expect(href.text).to eq('<code>www.mslinn.com</code>')
|
204
146
|
end
|
205
147
|
|
206
|
-
it
|
148
|
+
it 'implicitly computes external link from text with follow and notarget' do
|
207
149
|
href = described_class.send(
|
208
150
|
:new,
|
209
151
|
'href',
|
210
152
|
+ 'follow notarget www.mslinn.com',
|
211
153
|
parse_context
|
212
154
|
)
|
213
|
-
href.
|
214
|
-
linkk = href.send(:compute_linkk)
|
215
|
-
href.send(:globals_update, href.helper.argv, linkk)
|
155
|
+
href.render TestLiquidContext.new
|
216
156
|
expect(href.follow).to eq('')
|
217
157
|
expect(href.link).to eq('https://www.mslinn.com')
|
218
158
|
expect(href.target).to eq('')
|
219
159
|
expect(href.text).to eq('<code>www.mslinn.com</code>')
|
220
160
|
end
|
221
161
|
|
222
|
-
it
|
162
|
+
it 'implicitly computes external link from text with blank' do
|
223
163
|
href = described_class.send(
|
224
164
|
:new,
|
225
165
|
'href',
|
226
166
|
+ 'follow blank www.mslinn.com',
|
227
167
|
parse_context
|
228
168
|
)
|
229
|
-
href.
|
230
|
-
linkk = href.send(:compute_linkk)
|
231
|
-
href.send(:globals_update, href.helper.argv, linkk)
|
169
|
+
href.render TestLiquidContext.new
|
232
170
|
expect(href.follow).to eq('')
|
233
171
|
expect(href.link).to eq('https://www.mslinn.com')
|
234
172
|
expect(href.target).to eq(" target='_blank'")
|
235
173
|
expect(href.text).to eq('<code>www.mslinn.com</code>')
|
174
|
+
|
175
|
+
# hrefs = HashArray.instance_variable_get(:@global_hrefs)
|
176
|
+
# expect(hrefs).to eq(
|
177
|
+
# {
|
178
|
+
# "index.html" => [
|
179
|
+
# "<a href='https://feeds.soundcloud.com/users/soundcloud:users:7143896/sounds.rss' target='_blank' rel='nofollow'>SoundCloud RSS Feed</a>",
|
180
|
+
# "<a href='https://github.com/diasks2/confidential_info_redactor' target='_blank' rel='nofollow'><code>confidential_info_redactor</code></a>",
|
181
|
+
# "<a href='https://super-fake-merger.com' target='_blank' rel='nofollow'><code>super-fake-merger.com</code></a>",
|
182
|
+
# "<a href='https://www.mslinn.com' target='_blank'><code>www.mslinn.com</code></a>"
|
183
|
+
# ],
|
184
|
+
# }
|
185
|
+
# )
|
236
186
|
end
|
237
187
|
|
238
|
-
it
|
188
|
+
it 'obtains mailto without text' do
|
239
189
|
href = described_class.send(
|
240
190
|
:new,
|
241
191
|
'href',
|
242
192
|
+ 'mailto:mslinn@mslinn.com',
|
243
193
|
parse_context
|
244
194
|
)
|
245
|
-
href.
|
246
|
-
linkk = href.send(:compute_linkk)
|
247
|
-
href.send(:globals_update, href.helper.argv, linkk)
|
195
|
+
href.render TestLiquidContext.new
|
248
196
|
expect(href.follow).to eq('')
|
249
197
|
expect(href.link).to eq('mailto:mslinn@mslinn.com')
|
250
198
|
expect(href.target).to eq('')
|
251
199
|
expect(href.text).to eq('<code>mslinn@mslinn.com</code>')
|
252
200
|
end
|
253
201
|
|
254
|
-
it
|
202
|
+
it 'obtains mailto with text' do
|
255
203
|
href = described_class.send(
|
256
204
|
:new,
|
257
205
|
'href',
|
258
206
|
+ 'mailto:mslinn@mslinn.com Mike Slinn',
|
259
207
|
parse_context
|
260
208
|
)
|
261
|
-
href.
|
262
|
-
linkk = href.send(:compute_linkk)
|
263
|
-
href.send(:globals_update, href.helper.argv, linkk)
|
209
|
+
href.render TestLiquidContext.new
|
264
210
|
expect(href.follow).to eq('')
|
265
211
|
expect(href.link).to eq('mailto:mslinn@mslinn.com')
|
266
212
|
expect(href.target).to eq('')
|
data/spec/spec_helper.rb
CHANGED
@@ -1,10 +1,13 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require 'jekyll'
|
2
|
+
require 'jekyll_plugin_logger'
|
3
|
+
require 'liquid'
|
4
|
+
require 'fileutils'
|
5
|
+
require 'yaml'
|
3
6
|
require_relative "../lib/jekyll_href"
|
4
7
|
|
5
8
|
RSpec.configure do |config|
|
6
9
|
config.filter_run :focus
|
7
|
-
config.order = "random"
|
10
|
+
# config.order = "random"
|
8
11
|
config.run_all_when_everything_filtered = true
|
9
12
|
|
10
13
|
# See https://relishapp.com/rspec/rspec-core/docs/command-line/only-failures
|
@@ -12,3 +15,65 @@ RSpec.configure do |config|
|
|
12
15
|
|
13
16
|
config.filter_run_when_matching focus: true
|
14
17
|
end
|
18
|
+
|
19
|
+
Registers = Struct.new(:page, :site)
|
20
|
+
|
21
|
+
# Mock for Collections
|
22
|
+
class Collections
|
23
|
+
def values
|
24
|
+
[]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Mock for Site
|
29
|
+
class SiteMock
|
30
|
+
attr_reader :config
|
31
|
+
|
32
|
+
def initialize
|
33
|
+
@config = YAML.safe_load(File.read('../demo/_config.yml'))
|
34
|
+
@config['env'] = { 'JEKYLL_ENV' => 'development' }
|
35
|
+
end
|
36
|
+
|
37
|
+
def collections
|
38
|
+
Collections.new
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
class TestLiquidContext < Liquid::Context
|
43
|
+
def initialize
|
44
|
+
super
|
45
|
+
|
46
|
+
page = {
|
47
|
+
"content" => "blah blah",
|
48
|
+
"description" => "Jekyll plugin support demo",
|
49
|
+
"dir" => "/",
|
50
|
+
"excerpt" => nil,
|
51
|
+
"layout" => "default",
|
52
|
+
"name" => "index.html",
|
53
|
+
"path" => "index.html",
|
54
|
+
"title" => "Welcome",
|
55
|
+
"url" => "/",
|
56
|
+
}
|
57
|
+
|
58
|
+
@content = "Interior of the tag"
|
59
|
+
@registers = Registers.new(
|
60
|
+
page,
|
61
|
+
SiteMock.new
|
62
|
+
)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# Mock for Liquid::ParseContent
|
67
|
+
class TestParseContext < Liquid::ParseContext
|
68
|
+
attr_reader :line_number, :registers
|
69
|
+
|
70
|
+
def initialize
|
71
|
+
super
|
72
|
+
@line_number = 123
|
73
|
+
|
74
|
+
@registers = Registers.new(
|
75
|
+
{ 'path' => 'path/to/page.html' },
|
76
|
+
SiteMock.new
|
77
|
+
)
|
78
|
+
end
|
79
|
+
end
|
data/spec/status_persistence.txt
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
example_id | status | run_time |
|
2
2
|
----------------------------------------------------------------- | ------ | --------------- |
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
3
|
+
./spec/hash_array_spec.rb[1:1] | passed | 0.17104 seconds |
|
4
|
+
./spec/href_spec.rb[1:1] | passed | 0.03236 seconds |
|
5
|
+
./spec/href_spec.rb[1:2] | passed | 0.02884 seconds |
|
6
|
+
./spec/href_spec.rb[1:3] | passed | 0.02956 seconds |
|
7
|
+
./spec/href_spec.rb[1:4] | passed | 0.02841 seconds |
|
8
|
+
./spec/href_spec.rb[1:5] | passed | 0.02897 seconds |
|
9
|
+
./spec/href_spec.rb[1:6] | passed | 0.02866 seconds |
|
10
|
+
./spec/href_spec.rb[1:7] | passed | 0.02966 seconds |
|
11
|
+
./spec/href_spec.rb[1:8] | passed | 0.02983 seconds |
|
12
|
+
./spec/href_spec.rb[1:9] | passed | 0.02735 seconds |
|
13
|
+
./spec/href_spec.rb[1:10] | passed | 0.02928 seconds |
|
14
|
+
./spec/href_spec.rb[1:11] | passed | 0.02861 seconds |
|
15
|
+
./spec/href_spec.rb[1:12] | passed | 0.02958 seconds |
|
16
|
+
./spec/href_spec.rb[1:13] | passed | 0.02714 seconds |
|
17
|
+
/mnt/_/work/jekyll/my_plugins/jekyll_href/spec/href_spec.rb[1:1] | passed | 0.02582 seconds |
|
18
|
+
/mnt/_/work/jekyll/my_plugins/jekyll_href/spec/href_spec.rb[1:2] | passed | 0.01031 seconds |
|
19
|
+
/mnt/_/work/jekyll/my_plugins/jekyll_href/spec/href_spec.rb[1:3] | passed | 0.01045 seconds |
|
20
|
+
/mnt/_/work/jekyll/my_plugins/jekyll_href/spec/href_spec.rb[1:4] | passed | 0.01038 seconds |
|
21
|
+
/mnt/_/work/jekyll/my_plugins/jekyll_href/spec/href_spec.rb[1:5] | passed | 0.01081 seconds |
|
22
|
+
/mnt/_/work/jekyll/my_plugins/jekyll_href/spec/href_spec.rb[1:6] | passed | 0.01053 seconds |
|
23
|
+
/mnt/_/work/jekyll/my_plugins/jekyll_href/spec/href_spec.rb[1:7] | passed | 0.01125 seconds |
|
24
|
+
/mnt/_/work/jekyll/my_plugins/jekyll_href/spec/href_spec.rb[1:8] | passed | 0.01113 seconds |
|
25
|
+
/mnt/_/work/jekyll/my_plugins/jekyll_href/spec/href_spec.rb[1:9] | passed | 0.01088 seconds |
|
26
|
+
/mnt/_/work/jekyll/my_plugins/jekyll_href/spec/href_spec.rb[1:10] | passed | 0.01066 seconds |
|
27
|
+
/mnt/_/work/jekyll/my_plugins/jekyll_href/spec/href_spec.rb[1:11] | failed | 0.06099 seconds |
|
28
|
+
/mnt/_/work/jekyll/my_plugins/jekyll_href/spec/href_spec.rb[1:12] | passed | 0.01096 seconds |
|
29
|
+
/mnt/_/work/jekyll/my_plugins/jekyll_href/spec/href_spec.rb[1:13] | passed | 0.01028 seconds |
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jekyll_href
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.2.
|
4
|
+
version: 1.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Slinn
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-04-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: jekyll
|
@@ -44,6 +44,26 @@ dependencies:
|
|
44
44
|
- - ">="
|
45
45
|
- !ruby/object:Gem::Version
|
46
46
|
version: 0.3.1
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: jekyll_plugin_support
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - "~>"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 0.6.0
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: 0.6.1
|
57
|
+
type: :runtime
|
58
|
+
prerelease: false
|
59
|
+
version_requirements: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - "~>"
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: 0.6.0
|
64
|
+
- - ">="
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: 0.6.1
|
47
67
|
description: 'Generates an ''a href'' tag, possibly with target=''_blank'' and rel=''nofollow''.
|
48
68
|
|
49
69
|
'
|
@@ -59,19 +79,23 @@ files:
|
|
59
79
|
- README.md
|
60
80
|
- Rakefile
|
61
81
|
- jekyll_href.gemspec
|
82
|
+
- lib/hash_array.rb
|
83
|
+
- lib/href_summary_tag.rb
|
84
|
+
- lib/href_tag.rb
|
62
85
|
- lib/jekyll_href.rb
|
63
86
|
- lib/jekyll_href/version.rb
|
87
|
+
- spec/hash_array_spec.rb
|
64
88
|
- spec/href_spec.rb
|
65
89
|
- spec/spec_helper.rb
|
66
90
|
- spec/status_persistence.txt
|
67
|
-
homepage: https://www.mslinn.com/
|
91
|
+
homepage: https://www.mslinn.com/jekyll/3000-jekyll-plugins.html#href
|
68
92
|
licenses:
|
69
93
|
- MIT
|
70
94
|
metadata:
|
71
95
|
allowed_push_host: https://rubygems.org
|
72
96
|
bug_tracker_uri: https://github.com/mslinn/jekyll_href/issues
|
73
97
|
changelog_uri: https://github.com/mslinn/jekyll_href/CHANGELOG.md
|
74
|
-
homepage_uri: https://www.mslinn.com/
|
98
|
+
homepage_uri: https://www.mslinn.com/jekyll/3000-jekyll-plugins.html#href
|
75
99
|
source_code_uri: https://github.com/mslinn/jekyll_href
|
76
100
|
post_install_message: |2+
|
77
101
|
|
@@ -96,6 +120,7 @@ signing_key:
|
|
96
120
|
specification_version: 4
|
97
121
|
summary: Generates an 'a href' tag, possibly with target='_blank' and rel='nofollow'.
|
98
122
|
test_files:
|
123
|
+
- spec/hash_array_spec.rb
|
99
124
|
- spec/href_spec.rb
|
100
125
|
- spec/spec_helper.rb
|
101
126
|
- spec/status_persistence.txt
|