jekyll_href 1.2.1 → 1.2.3
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 +4 -4
- data/.rubocop.yml +10 -3
- data/CHANGELOG.md +9 -0
- data/README.md +103 -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 +226 -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: f273b4ad20431d42f67bd6a8bba43823e158b4239d385951371e5511f31483f6
|
4
|
+
data.tar.gz: 13ce74af244bd5d9d26c44a7ebeb340126f729f084cddf04c75d0b79e83e973e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 69169786943109c5f2fb288a430d247f8fa3a46b4d94c78607c012f3a9abd4116f38e66a4071e11c8bb53e8d21e7b3efe716aaf32d7a93c73d670026a24038bc
|
7
|
+
data.tar.gz: b37d5401822827f70f9b1e00f5eef1e93f8cab00c97a808409d71e6f173d99c0dc7bab5e33c07c2e41b98d47a2749a2e9e771588f167c8b269fa50b07c47cc96
|
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,12 @@
|
|
1
|
+
## 1.2.3 / 2023-05-16
|
2
|
+
* Added `label` option.
|
3
|
+
|
4
|
+
## 1.2.2 / 2023-03-25
|
5
|
+
* Added **References** capability:
|
6
|
+
* Added `summary_exclude` keyword option to `href` tag.
|
7
|
+
* Added `href_summary` tag.
|
8
|
+
* If a URL appears in more than one `href` with different `follow` values a warning is logged.
|
9
|
+
|
1
10
|
## 1.2.1 / 2023-03-21
|
2
11
|
* Added `shy` and `wbr` options.
|
3
12
|
|
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://`,
|
@@ -88,6 +85,15 @@ If both are specified, `blank` prevails.
|
|
88
85
|
### `follow`
|
89
86
|
To suppress the `nofollow` attribute, preface the link with the word `follow`.
|
90
87
|
|
88
|
+
### `label='whatever you want'`
|
89
|
+
If the text to be linked contains an optional keyword argument,
|
90
|
+
for example `summary`, that word will be removed from the displayed link text,
|
91
|
+
unless the link text is provided via the `label` option.
|
92
|
+
Both of the following produce the same output:
|
93
|
+
```
|
94
|
+
{% href https://mslinn.com label="This is a summary" %}
|
95
|
+
{% href label="This is a summary" https://mslinn.com %}
|
96
|
+
```
|
91
97
|
|
92
98
|
### `notarget`
|
93
99
|
To suppress the `target` attribute, preface the link with the word `notarget`.
|
@@ -117,7 +123,7 @@ Expands to:
|
|
117
123
|
```
|
118
124
|
|
119
125
|
### `shy`
|
120
|
-
`shy` is only applicable for syntax 3 (implicit URL).
|
126
|
+
The `shy` keyword option is only applicable for syntax 3 (implicit URL).
|
121
127
|
This option causes displayed urls to have an [`­`](https://developer.mozilla.org/en-US/docs/Web/CSS/hyphens) inserted after each slash (/).
|
122
128
|
If both `shy` and `wbr` are specified, `wbr` prevails.
|
123
129
|
|
@@ -130,8 +136,22 @@ Expands to:
|
|
130
136
|
<a href="https://mslinn.com/path/to/page.html" rel="nofollow" target="_blank">mslinn.com/­path/­to/­page.html</a>
|
131
137
|
```
|
132
138
|
|
139
|
+
### `summary`
|
140
|
+
The `summary` name/value option provides an override for the linked text in the **References** section
|
141
|
+
generated by the `{% href_summary %}` tag.
|
142
|
+
If the value is the empty string, or no value is provided, the `href` tag is not included in the page summary.
|
143
|
+
|
144
|
+
|
145
|
+
### `summary_exclude`
|
146
|
+
The `summary_exclude` keyword option prevents this `href` tag from appearing in the summary
|
147
|
+
produced by the [<code>href_summary</code> tag](#href_summary).
|
148
|
+
You probably want all of your menu items (whose links are generated by the `href` tag) to have this keyword option.
|
149
|
+
|
150
|
+
`mailto:` links are always excluded, so there is no need to use this keyword option for those types of links.
|
151
|
+
|
152
|
+
|
133
153
|
### `wbr`
|
134
|
-
`wbr` is only applicable for syntax 3 (implicit URL).
|
154
|
+
The `wbr` keyword option is only applicable for syntax 3 (implicit URL).
|
135
155
|
It add [line break opportunites](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/wbr).
|
136
156
|
This option causes displayed urls to have an `<wbr>` inserted after each slash (/).
|
137
157
|
If both `shy` and `wbr` are specified, `wbr` prevails.
|
@@ -185,6 +205,81 @@ Expands to:
|
|
185
205
|
Substitutions are only made to the URL, not to the linked text.
|
186
206
|
|
187
207
|
|
208
|
+
## References Generation
|
209
|
+
The `href` usages on each page can be summarized at the bottom of the pages in a **References** section.
|
210
|
+
Links are presented in the summary in the order they appear in the page.
|
211
|
+
|
212
|
+
The summary is produced by the `href_summary` tag.
|
213
|
+
Usage is:
|
214
|
+
|
215
|
+
```html
|
216
|
+
{% href_summary [options] %}
|
217
|
+
```
|
218
|
+
|
219
|
+
`Href` tag options are used to generate the summary links,
|
220
|
+
just as they were in the text above the **References** summary section.
|
221
|
+
The only exception is the `summary` option, which overrides the linked text.
|
222
|
+
|
223
|
+
If more than one `href` tag specifies a URL,
|
224
|
+
the first one that appears in the page sets the value of the linked text.
|
225
|
+
|
226
|
+
If a URL appears in more than one `href` with different `follow` values, a warning is logged.
|
227
|
+
|
228
|
+
|
229
|
+
### Included `href` Tags
|
230
|
+
The following `href` tags are included in the summary:
|
231
|
+
|
232
|
+
- Those with links that start with `http` are always included.
|
233
|
+
- Those with [relative links](https://www.w3.org/TR/WD-html40-970917/htmlweb.html#h-5.1.2),
|
234
|
+
and have the `include_local` keyword option.
|
235
|
+
|
236
|
+
### Excluded `href` Tags
|
237
|
+
The following `href` tags are excluded from the summary:
|
238
|
+
|
239
|
+
- Those with links that start with `mailto:`.
|
240
|
+
- Those having the `summary_exclude` keyword option.
|
241
|
+
|
242
|
+
|
243
|
+
### Example
|
244
|
+
Given these `href` and `href_summary` usages in a web page:
|
245
|
+
|
246
|
+
```html
|
247
|
+
{% href https://rubygems.org RubyGems.org %}
|
248
|
+
{% href summary="Mothership" https://jekyllrb.com/ Jekyll %}
|
249
|
+
{% href summary="Mike Slinn" mslinn.com %}
|
250
|
+
{% href https://mslinn.com Mike Slinn %}
|
251
|
+
{% href summary="Front page of this website" / Front page %}
|
252
|
+
|
253
|
+
{% href_summary attribution include_local %}
|
254
|
+
```
|
255
|
+
|
256
|
+
Then the generated HTML looks like the following:
|
257
|
+
|
258
|
+
```html
|
259
|
+
<h2 id="reference">References</h2>
|
260
|
+
<ol>
|
261
|
+
<li><a href='https://rubygems.org' rel='nofollow' target='_blank'>RubyGems.org</a></li>
|
262
|
+
<li><a href='https://jekyllrb.com/' rel='nofollow' target='_blank'>Mothership</a></li>
|
263
|
+
<li><a href='https://mslinn.com/' rel='nofollow' target='_blank'><code>mslinn.com</code></a></li>
|
264
|
+
</ol>
|
265
|
+
|
266
|
+
<h2 id="local_reference">Local References</h2>
|
267
|
+
<ol>
|
268
|
+
<li><a href='/'>Front page of this website</a></li>
|
269
|
+
</ol>
|
270
|
+
|
271
|
+
<div id="jps_attribute_735866" class="jps_attribute">
|
272
|
+
<div>
|
273
|
+
<a href="https://www.mslinn.com/jekyll/3000-jekyll-plugins.html#href" target="_blank" rel="nofollow">
|
274
|
+
Generated by the jekyll_href v1.2.2 Jekyll plugin, written by Mike Slinn 2023-04-13.
|
275
|
+
</a>
|
276
|
+
</div>
|
277
|
+
</div>
|
278
|
+
```
|
279
|
+
|
280
|
+
You can read about the `attribution` option [here](https://www.mslinn.com/jekyll/10200-jekyll-plugin-support.html#attribution).
|
281
|
+
|
282
|
+
|
188
283
|
## Additional Information
|
189
284
|
More information is available on my website about
|
190
285
|
[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,226 @@
|
|
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
|
+
if @summary == true
|
59
|
+
warning = <<~END_WARNING
|
60
|
+
Warning: a href plugin keyword option was detected in the link text for #{@path} on line #{line_number}.
|
61
|
+
The href tag will not be included in the summary, and the link text will not have the word summary included.
|
62
|
+
This is probably unintentional. Consider using the label option to correct this problem."
|
63
|
+
END_WARNING
|
64
|
+
puts warning.red
|
65
|
+
return
|
66
|
+
end
|
67
|
+
return if @summary.class != String || @summary.empty?
|
68
|
+
|
69
|
+
@summary = @summary[0].upcase + @summary[1..]
|
70
|
+
@summary_href = "<a href='#{@link_save}'#{@target}#{@follow}>#{@summary}</a>"
|
71
|
+
mini_href = MiniHref.new(
|
72
|
+
follow: @follow,
|
73
|
+
html: @summary_href,
|
74
|
+
line_number: @line_number,
|
75
|
+
link: @link_save,
|
76
|
+
link_save: @link_save,
|
77
|
+
path: @path,
|
78
|
+
summary_exclude: @summary_exclude,
|
79
|
+
summary_href: @summary_href
|
80
|
+
)
|
81
|
+
if @link_save.start_with? 'http'
|
82
|
+
add_global_link_for_page mini_href
|
83
|
+
else
|
84
|
+
add_local_link_for_page mini_href
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# Does not look at or compute @link
|
89
|
+
def compute_linkk
|
90
|
+
return @link if @link
|
91
|
+
|
92
|
+
linkk = @url
|
93
|
+
if linkk.nil? || !linkk
|
94
|
+
linkk = @helper.argv&.shift
|
95
|
+
@helper.params&.shift
|
96
|
+
@helper.keys_values&.delete(linkk)
|
97
|
+
dump_linkk_relations(linkk) if linkk.nil?
|
98
|
+
elsif @url.to_s.empty?
|
99
|
+
dump_linkk_relations(linkk)
|
100
|
+
end
|
101
|
+
linkk
|
102
|
+
end
|
103
|
+
|
104
|
+
def dump_linkk_relations(linkk)
|
105
|
+
msg = <<~END_MESSAGE
|
106
|
+
jekyll_href error: no url was provided on #{@path}:#{@line_number}.
|
107
|
+
@helper.markup=#{@helper.markup}
|
108
|
+
@helper.argv='#{@helper.argv}'
|
109
|
+
linkk='#{linkk}'
|
110
|
+
@match='#{@match}'
|
111
|
+
@url='#{@url}'
|
112
|
+
@follow='#{@follow}
|
113
|
+
@target='#{@target}'
|
114
|
+
END_MESSAGE
|
115
|
+
abort msg.red
|
116
|
+
end
|
117
|
+
|
118
|
+
# Sets @follow, @helper, @match, @path, @shy, @target, @url, @wbr
|
119
|
+
def globals_initial
|
120
|
+
@path = @page['path']
|
121
|
+
AllCollectionsHooks.compute(@site)
|
122
|
+
|
123
|
+
@blank = @helper.parameter_specified? 'blank'
|
124
|
+
@follow = @helper.parameter_specified?('follow') ? '' : " rel='nofollow'"
|
125
|
+
@match = @helper.parameter_specified? 'match'
|
126
|
+
@label = @helper.parameter_specified? 'label'
|
127
|
+
@summary_exclude = @helper.parameter_specified? 'summary_exclude'
|
128
|
+
@shy = @helper.parameter_specified? 'shy'
|
129
|
+
@summary = @helper.parameter_specified? 'summary'
|
130
|
+
@target = @blank ? " target='_blank'" : nil
|
131
|
+
@target ||= @helper.parameter_specified?('notarget') ? '' : " target='_blank'"
|
132
|
+
@url = @helper.parameter_specified? 'url'
|
133
|
+
@wbr = @helper.parameter_specified? 'wbr'
|
134
|
+
end
|
135
|
+
|
136
|
+
# Might set @follow, @linkk, @target, and @text
|
137
|
+
def globals_update(tokens, linkk)
|
138
|
+
if linkk.start_with? 'mailto:'
|
139
|
+
@link = linkk
|
140
|
+
@target = @follow = ''
|
141
|
+
@text = @helper.argv.join(' ')
|
142
|
+
if @text.empty?
|
143
|
+
text = linkk.delete_prefix('mailto:')
|
144
|
+
@text = "<code>#{text}</code>"
|
145
|
+
end
|
146
|
+
return
|
147
|
+
else
|
148
|
+
@text = @label || tokens.join(' ').strip
|
149
|
+
if @text.to_s.empty?
|
150
|
+
text = linkk
|
151
|
+
text = linkk.gsub('/', '/­') if @shy
|
152
|
+
text = linkk.gsub('/', '/<wbr>') if @wbr
|
153
|
+
@text = "<code>#{text}</code>"
|
154
|
+
@link = linkk.start_with?('http') ? linkk : "https://#{linkk}"
|
155
|
+
else
|
156
|
+
@link = if @shy
|
157
|
+
linkk.gsub('/', '/­')
|
158
|
+
elsif @wbr
|
159
|
+
linkk.gsub('/', '/<wbr>')
|
160
|
+
else
|
161
|
+
linkk
|
162
|
+
end
|
163
|
+
end
|
164
|
+
@link_save = @link
|
165
|
+
end
|
166
|
+
|
167
|
+
return if @link.start_with? 'http'
|
168
|
+
|
169
|
+
@follow = ''
|
170
|
+
@target = '' unless @blank
|
171
|
+
end
|
172
|
+
|
173
|
+
def handle_match
|
174
|
+
match_post
|
175
|
+
@follow = ''
|
176
|
+
@target = '' unless @blank
|
177
|
+
end
|
178
|
+
|
179
|
+
# Might set @link and @text
|
180
|
+
def match_post
|
181
|
+
config = @site.config['href']
|
182
|
+
@die_if_nomatch = !config.nil? && config['nomatch'] && config['nomatch'] == 'fatal'
|
183
|
+
@path, @fragment = @link.split('#')
|
184
|
+
|
185
|
+
@logger.debug do
|
186
|
+
<<~END_DEBUG
|
187
|
+
@link=#{@link}
|
188
|
+
@site.posts.docs[0].url = #{@site.posts.docs[0].url}
|
189
|
+
@site.posts.docs[0].path = #{@site.posts.docs[0].path}
|
190
|
+
END_DEBUG
|
191
|
+
end
|
192
|
+
|
193
|
+
all_urls = @site.all_collections.map(&:url)
|
194
|
+
compute_link_and_text(all_urls)
|
195
|
+
end
|
196
|
+
|
197
|
+
def compute_link_and_text(all_urls)
|
198
|
+
url_matches = all_urls.select { |url| url&.include? @path }
|
199
|
+
case url_matches.length
|
200
|
+
when 0
|
201
|
+
abort "href error: No url matches '#{@link}'" if @die_if_nomatch
|
202
|
+
@link_save = @link = '#'
|
203
|
+
@text = "<i>#{@link} is not available</i>"
|
204
|
+
when 1
|
205
|
+
@link = url_matches.first
|
206
|
+
@link = "#{@link}##{@fragment}" if @fragment
|
207
|
+
@link_save = @link
|
208
|
+
else
|
209
|
+
abort "Error: More than one url matched '#{@path}': #{url_matches.join(', ')}"
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
# Replace names in plugin-vars with values
|
214
|
+
def replace_vars(text)
|
215
|
+
variables = @site.config['plugin-vars']
|
216
|
+
return text unless variables
|
217
|
+
|
218
|
+
variables.each do |name, value|
|
219
|
+
text = text.gsub "{{#{name}}}", value
|
220
|
+
end
|
221
|
+
text
|
222
|
+
end
|
223
|
+
|
224
|
+
JekyllPluginHelper.register(self, 'href')
|
225
|
+
end
|
226
|
+
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.3
|
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-05-17 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
|