jekyll_href 1.1.0 → 1.2.2

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.
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('/', '/&shy;') 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('/', '/&shy;')
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
@@ -1,3 +1,3 @@
1
1
  module JekyllHrefVersion
2
- VERSION = '1.1.0'.freeze
2
+ VERSION = '1.2.2'.freeze
3
3
  end
data/lib/jekyll_href.rb CHANGED
@@ -1,177 +1,9 @@
1
- require 'jekyll_all_collections'
2
- require 'jekyll_plugin_logger'
3
- require 'liquid'
4
- require_relative 'jekyll_href/version'
5
- require_relative './jekyll_tag_helper2'
1
+ require_relative 'href_tag'
2
+ require_relative 'href_summary_tag'
6
3
 
7
- # @author Copyright 2020 Michael Slinn
8
- # @license SPDX-License-Identifier: Apache-2.0
9
- # Generates an href.
4
+ HrefError = Class.new(Liquid::Error)
10
5
 
11
- # Implements href Jekyll tag
12
- class ExternalHref < Liquid::Tag # rubocop:disable Metrics/ClassLength
13
- attr_reader :follow, :helper, :line_number, :match, :page, :path, :site, :text, :target, :url
14
- attr_accessor :link
15
-
16
- # @param tag_name [String] is the name of the tag, which we already know.
17
- # @param markup [String] the arguments from the web page.
18
- # @param _tokens [Liquid::ParseContext] tokenized command line
19
- # By default it has two keys: :locale and :line_numbers, the first is a Liquid::I18n object, and the second,
20
- # a boolean parameter that determines if error messages should display the line number the error occurred.
21
- # This argument is used mostly to display localized error messages on Liquid built-in Tags and Filters.
22
- # See https://github.com/Shopify/liquid/wiki/Liquid-for-Programmers#create-your-own-tags
23
- # @return [void]
24
- def initialize(tag_name, markup, _tokens)
25
- super
26
- markup = '' if markup.nil?
27
- markup.strip!
28
-
29
- @logger = PluginMetaLogger.instance.new_logger(self, PluginMetaLogger.instance.config)
30
- @helper = JekyllTagHelper2.new(tag_name, markup, @logger)
31
- end
32
-
33
- # Method prescribed by the Jekyll plugin lifecycle.
34
- # @param liquid_context [Liquid::Context]
35
- # @return [String]
36
- def render(liquid_context)
37
- super
38
- globals_initial(liquid_context)
39
- linkk = compute_linkk
40
- linkk = replace_vars(linkk)
41
- @link_save = linkk
42
- @helper_save = @helper.clone
43
- globals_update(@helper.argv, linkk) # Sets @link and @text, might clear @follow and @target
44
- handle_match if @match
45
- "<a href='#{@link}'#{@target}#{@follow}>#{@text}</a>"
46
- end
47
-
48
- private
49
-
50
- # Does not look at or compute @link
51
- def compute_linkk
52
- return @link if @link
53
-
54
- linkk = @url
55
- if linkk.nil? || !linkk
56
- linkk = @helper.argv&.shift
57
- @helper.params&.shift
58
- @helper.keys_values&.delete(linkk)
59
- dump_linkk_relations(linkk) if linkk.nil?
60
- elsif @url.to_s.empty?
61
- dump_linkk_relations(linkk)
62
- end
63
- linkk
64
- end
65
-
66
- def dump_linkk_relations(linkk)
67
- msg = <<~END_MESSAGE
68
- jekyll_href error: no url was provided on #{@path}:#{@line_number}.
69
- @helper.markup=#{@helper.markup}
70
- @helper.argv='#{@helper.argv}'
71
- linkk='#{linkk}'
72
- @match='#{@match}'
73
- @url='#{@url}'
74
- @follow='#{@follow}
75
- @target='#{@target}'
76
- END_MESSAGE
77
- abort msg.red
78
- end
79
-
80
- def globals_initial(liquid_context)
81
- # Sets @follow, @helper, @match, @page, @path, @site, @target, @url
82
- @helper.liquid_context = liquid_context
83
-
84
- @page = liquid_context.registers[:page]
85
- @path = @page['path']
86
- @site = liquid_context.registers[:site]
87
- AllCollectionsHooks.compute(@site)
88
-
89
- @follow = @helper.parameter_specified?('follow') ? '' : " rel='nofollow'"
90
- @match = @helper.parameter_specified?('match')
91
- @blank = @helper.parameter_specified?('blank')
92
- @target = @blank ? " target='_blank'" : nil
93
- @target ||= @helper.parameter_specified?('notarget') ? '' : " target='_blank'"
94
- @url = @helper.parameter_specified?('url')
95
- end
96
-
97
- # Might set @follow, @linkk, @target, and @text
98
- def globals_update(tokens, linkk)
99
- if linkk.start_with? 'mailto:'
100
- @link = linkk
101
- @target = @follow = ''
102
- @text = @helper.argv.join(' ')
103
- if @text.empty?
104
- text = linkk.delete_prefix('mailto:')
105
- @text = "<code>#{text}</code>"
106
- end
107
- return
108
- else
109
- @text = tokens.join(' ').strip
110
- if @text.to_s.empty?
111
- @text = "<code>#{linkk}</code>"
112
- @link = "https://#{linkk}"
113
- else
114
- @link = linkk
115
- end
116
- end
117
-
118
- return if @link.start_with? 'http'
119
-
120
- @follow = ''
121
- @target = '' unless @blank
122
- end
123
-
124
- def handle_match
125
- match_post
126
- @follow = ''
127
- @target = '' unless @blank
128
- end
129
-
130
- # Might set @link and @text
131
- def match_post
132
- config = @site.config['href']
133
- @die_if_nomatch = !config.nil? && config['nomatch'] && config['nomatch'] == 'fatal'
134
- @path, @fragment = @link.split('#')
135
-
136
- @logger.debug do
137
- <<~END_DEBUG
138
- @link=#{@link}
139
- @site.posts.docs[0].url = #{@site.posts.docs[0].url}
140
- @site.posts.docs[0].path = #{@site.posts.docs[0].path}
141
- END_DEBUG
142
- end
143
-
144
- all_urls = @site.all_collections.map(&:url)
145
- compute_link_and_text(all_urls)
146
- end
147
-
148
- def compute_link_and_text(all_urls)
149
- url_matches = all_urls.select { |url| url&.include? @path }
150
- case url_matches.length
151
- when 0
152
- abort "href error: No url matches '#{@link}'" if @die_if_nomatch
153
- @link = '#'
154
- @text = "<i>#{@link} is not available</i>"
155
- when 1
156
- @link = url_matches.first
157
- @link = "#{@link}\##{@fragment}" if @fragment
158
- else
159
- abort "Error: More than one url matched '#{@path}': #{url_matches.join(', ')}"
160
- end
161
- end
162
-
163
- # Replace names in plugin-vars with values
164
- def replace_vars(text)
165
- variables = @site.config['plugin-vars']
166
- return text unless variables
167
-
168
- variables.each do |name, value|
169
- text = text.gsub "{{#{name}}}", value
170
- end
171
- @logger.debug { "@link=#{@link}" }
172
- text
173
- end
6
+ module JekyllHrefModule
7
+ include HrefTag
8
+ include HrefSummaryTag
174
9
  end
175
-
176
- PluginMetaLogger.instance.info { "Loaded jekyll_href v#{JekyllHrefVersion::VERSION} plugin." }
177
- Liquid::Template.register_tag('href', ExternalHref)
@@ -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