jekyll_flexible_include 2.0.4 → 2.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 60cf6d0ee5123d82f4a0ae31d85db6ffcbb7326693af3dc457dc64110de42d88
4
- data.tar.gz: b06fcc1ef1439efdf98effed553c714583bbe600707719a7252c93079e8e7a5e
3
+ metadata.gz: 7728aa7304d9fef053bb7b6f0e5adb59938a13711764f5ec1615497d54e23845
4
+ data.tar.gz: 1ef45a4764e136856e80e9a874cfa6e30ac1a9bc2523a10a024fa79bafc1b3d5
5
5
  SHA512:
6
- metadata.gz: 2eab4ce0e37112c0499703ecd30211b01ae2b38e1ec89f01f94b188dfdf539ec7dd1a5f8aa4f4be7a3d9dae7d30d71797687a8a00c916e1cf948d6b1326403ba
7
- data.tar.gz: ab036ab986241031929f7f4ac335312e4fcb81a66019f196278c38d247292f22c69b009fe269b7e19633ea5a6645e1b86db81a2b60e172a16b3a6d4cb5791f96
6
+ metadata.gz: 33c164b768d259e680458b14fab226d7fe038685a8dc98b459140a812628c8e9978e200e1ea3da414be678ebaca5f73e3b42957f26879162d6ce9c874f5346d2
7
+ data.tar.gz: 43b56da5e19d31a4aa51c87ba21d284c57f1f242a2f25f16bf71d3524ad620df09ba98faf18b234992073ddb2b09fbe89a912a6a15877d9ce1b71608eaa6ea33
data/.rubocop.yml CHANGED
@@ -9,6 +9,9 @@ AllCops:
9
9
  NewCops: enable
10
10
  TargetRubyVersion: 2.6
11
11
 
12
+ # Gemspec/RequireMFA:
13
+ # Enabled: false
14
+
12
15
  Layout/LineLength:
13
16
  Max: 150
14
17
 
@@ -18,6 +21,9 @@ Layout/MultilineMethodCallIndentation:
18
21
  Metrics/BlockLength:
19
22
  Enabled: false
20
23
 
24
+ Style/CommandLiteral:
25
+ Enabled: false
26
+
21
27
  Style/PercentLiteralDelimiters:
22
28
  Enabled: false
23
29
 
@@ -29,6 +35,3 @@ Style/StringLiterals:
29
35
 
30
36
  Style/StringLiteralsInInterpolation:
31
37
  Enabled: false
32
-
33
- Gemspec/RequireMFA:
34
- Enabled: false
data/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ ## 2.0.5 / 2022-04-11
2
+ * Now using <code>Shellwords</code> and <code>KeyValueParser</code> instead of a homegrown parser.
3
+ * Refactored helper methods to jekyll_tag_helper.rb
4
+ * Looks up values for liquid variable references from several scopes.
5
+ * Suppresses stack dump when an error occurs.
6
+ * Deleted a lot of old cruft.
7
+ * Added pre, label and copy_button optional parameters
8
+
1
9
  ## 2.0.4 / 2022-04-05
2
10
  * Updated to `jekyll_plugin_logger` v2.1.0
3
11
 
data/README.md CHANGED
@@ -22,14 +22,27 @@ This plugin supports 4 types of includes:
22
22
  In addition, filenames that require environment expansion because they contain a <code>$</code> character are
23
23
  expanded according to the environment variables defined when <code>jekyll build</code> executes.
24
24
 
25
- ### Syntax:
25
+ ### Syntax
26
+ The following are equivalent:
26
27
  ```
27
- {% flexible_include path [ do_not_escape='true' ] %}
28
+ {% flexible_include path [ OPTIONS ] %}
29
+ {% flexible_include 'path' [ OPTIONS ] %}
30
+ {% flexible_include "path" [ OPTIONS ] %}
28
31
  ```
29
32
 
30
- The included file will escape characters <code>&lt;</code>, <code>{</code> and <code>}</code> unless <code>do_not_escape</code>
31
- is specified with a value other than <code>false</code>.
32
- Note that the [square brackets] merely indicate an optional parameter and are not intended to be literally written.
33
+ By default, the included file will escape characters <code>&lt;</code>, <code>{</code> and <code>}</code>
34
+ unless <code>do_not_escape</code> is specified.
35
+ Note that the [square brackets] merely indicate optional parameters and are not intended to be written literally.
36
+
37
+ ### Options
38
+ * `do_not_escape` includes the content without HTML escaping it.
39
+ * `pre` causes the included file to be wrapped inside a &lt;pre>&lt;/pre> tag, no label is generated.
40
+
41
+ The following options imply `pre`:
42
+ * `download` uses the name of the file as a label, and displays it above the &lt;pre>&lt;/pre> tag. Clicking the label causes the file to be downloaded.
43
+ * `copy_button` draws an icon at the top right of the &lt;pre>&lt;/pre> tag that causes the included contents to be copied to the clipboard.
44
+ * `label` specifies that an automatically generated label be placed above the contents. There is no need to specify this option if `download` or `copy_button` options are provided.
45
+ * `label="blah blah"` specifies a label for the contents; this value overrides the default label. The value can be enclosed in single or double quotes.
33
46
 
34
47
 
35
48
  ### Additional Information
@@ -62,7 +75,7 @@ Or install it yourself as:
62
75
 
63
76
  ## Examples
64
77
 
65
- 1. Include files without parameters; all four types of includes are shown.
78
+ 1. Include files, escaping any HTML markup so it appears as written; all four types of includes are shown.
66
79
  ```
67
80
  {% flexible_include '../../folder/outside/jekyll/site/foo.html' %}
68
81
  {% flexible_include 'folder/within/jekyll/site/bar.js' %}
@@ -74,7 +87,7 @@ Or install it yourself as:
74
87
 
75
88
  2. Include a JSON file (without escaping characters).
76
89
  ```
77
- {% flexible_include '~/folder/under/home/directory/foo.html' do_not_escape='true' %}
90
+ {% flexible_include '~/folder/under/home/directory/foo.html' do_not_escape %}
78
91
  ```
79
92
 
80
93
  ## Additional Information
@@ -125,14 +138,14 @@ $ gem info jekyll_flexible_include
125
138
 
126
139
  *** LOCAL GEMS ***
127
140
 
128
- jekyll_flexible_include (1.0.0)
129
- Author: Mike Slinn
130
- Homepage:
131
- https://github.com/mslinn/jekyll_flexible_include
141
+ jekyll_flexible_include (2.0.4)
142
+ Authors: Mike Slinn, Tan Nhu, Maarten Brakkee
143
+ Homepage: https://www.mslinn.com/blog/2020/10/03/jekyll-plugins.html#flexibleInclude
132
144
  License: MIT
133
- Installed at: /home/mslinn/.gems
145
+ Installed at (2.0.4): /home/mslinn/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0
134
146
 
135
- Generates Jekyll logger with colored output.
147
+ Jekyll plugin supports various ways to include content into the
148
+ generated site.
136
149
  ```
137
150
 
138
151
 
@@ -5,7 +5,7 @@ require_relative "lib/flexible_include/version"
5
5
  Gem::Specification.new do |spec|
6
6
  github = "https://github.com/mslinn/jekyll_flexible_include_plugin"
7
7
 
8
- spec.authors = ["Mike Slinn"]
8
+ spec.authors = ["Mike Slinn", "Tan Nhu", "Maarten Brakkee"]
9
9
  spec.bindir = "exe"
10
10
  spec.description = <<~END_OF_DESC
11
11
  Jekyll's built-in include tag only supports including files within the _includes folder.
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module JekyllFlexibleIncludePluginVersion
4
- VERSION = "2.0.4"
4
+ VERSION = "2.0.5"
5
5
  end
@@ -2,139 +2,74 @@
2
2
 
3
3
  require "jekyll"
4
4
  require "jekyll_plugin_logger"
5
+ require "securerandom"
5
6
  require_relative "flexible_include/version"
7
+ require_relative "jekyll_tag_helper"
6
8
 
7
9
  module JekyllFlexibleIncludeName
8
10
  PLUGIN_NAME = "flexible_include"
9
11
  end
10
12
 
11
- class FlexibleIncludeError < StandardError
12
- attr_accessor :path
13
-
14
- def initialize(msg, path)
15
- super
16
- @path = path
17
- end
18
- end
19
-
20
13
  class FlexibleInclude < Liquid::Tag
21
- VALID_SYNTAX = %r!
22
- ([\w-]+)\s*=\s*
23
- (?:"([^"\\]*(?:\\.[^"\\]*)*)"|'([^'\\]*(?:\\.[^'\\]*)*)'|([\w.-]+))
24
- !x.freeze
25
- VARIABLE_SYNTAX = %r!
26
- (?<variable>[^{]*(\{\{\s*[\w\-.]+\s*(\|.*)?\}\}[^\s{}]*)+)
27
- (?<params>.*)
28
- !mx.freeze
29
-
30
- FULL_VALID_SYNTAX = %r!\A\s*(?:#{VALID_SYNTAX}(?=\s|\z)\s*)*\z!.freeze
31
- VALID_FILENAME_CHARS = %r!^[\w/\.-]+$!.freeze
32
-
33
- def initialize(tag_name, markup, parse_context)
14
+ FlexibleIncludeError = Class.new(Liquid::Error)
15
+
16
+ # @param tag_name [String] the name of the tag, which we already know.
17
+ # @param markup [String] the arguments from the tag, as a single string.
18
+ # @param parse_context [Liquid::ParseContext] hash that stores Liquid options.
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
+ def initialize(tag_name, markup, _parse_context)
34
24
  super
35
25
  @logger = PluginMetaLogger.instance.new_logger(self, PluginMetaLogger.instance.config)
36
- matched = markup.strip.match(VARIABLE_SYNTAX)
37
- if matched
38
- @file = matched["variable"].strip
39
- @params = matched["params"].strip
40
- else
41
- @file, @params = markup.strip.split(%r!\s+!, 2)
26
+ @helper = JekyllTagHelper.new(tag_name, markup, @logger)
27
+ end
28
+
29
+ # @param liquid_context [Liquid::Context]
30
+ def render(liquid_context) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity
31
+ @helper.liquid_context = liquid_context
32
+ @do_not_escape = @helper.parameter_specified? "do_not_escape"
33
+ @download = @helper.parameter_specified? "download"
34
+ @label = @helper.parameter_specified? "label"
35
+ @label_specified = @label
36
+ @copy_button = @helper.parameter_specified? "copyButton"
37
+ @pre = @copy_button || @download || @label_specified || @helper.parameter_specified?("pre") # Download or label implies pre
38
+ filename = @helper.params.first # Do this after all options have been checked for
39
+ @label ||= filename
40
+
41
+ # If a label was specified, use it, otherwise concatenate any dangling parameters and use that as the label
42
+ @label ||= @helper.params[1..].join(" ")
43
+
44
+ @logger.debug("filename=#{filename}")
45
+
46
+ path = JekyllTagHelper.expand_env(filename)
47
+ case path
48
+ when /\A\// # Absolute path
49
+ @logger.debug { "Absolute path=#{path}, filename=#{filename}" }
50
+ when /\A~/ # Relative path to user's home directory
51
+ @logger.debug { "User home start filename=#{filename}, path=#{path}" }
52
+ filename.slice! "~/"
53
+ path = File.join(ENV['HOME'], filename)
54
+ @logger.debug { "User home end filename=#{filename}, path=#{path}" }
55
+ when /\A!/ # Run command and return response
56
+ filename = JekyllTagHelper.remove_quotes(@helper.argv.first)
57
+ filename.slice! "!"
58
+ contents = run(filename)
59
+ else # Relative path
60
+ site = liquid_context.registers[:site]
61
+ source = File.expand_path(site.config['source']) # website root directory
62
+ path = File.join(source, filename) # Fully qualified path of include file from relative path
63
+ @relative = true
64
+ @logger.debug { "Relative end filename=#{filename}, path=#{path}" }
42
65
  end
43
- @markup = markup
44
- @logger.debug("initialize: @markup=#{@markup}")
45
- @parse_context = parse_context
46
- end
47
-
48
- # @param context [Liquid::Context]
49
- def render(context) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
50
- markup = @markup
51
- @logger.debug { "markup='#{markup}'" }
52
- markup = sanitize_parameter(markup)
53
- markup = expand_env(markup)
54
- path = markup
55
- if /\A\//.match(markup) # Is the file absolute?
56
- @logger.debug { "Absolute path=#{path}, markup=#{markup}" }
57
- elsif /\A~/.match(markup) # Relative path to user's home directory?
58
- @logger.debug { "Relative start markup=#{markup}, path=#{path}" }
59
- markup.slice! "~/"
60
- path = File.join(ENV['HOME'], markup)
61
- @logger.debug { "Relative end markup=#{markup}, path=#{path}" }
62
- elsif /\A\!/.match(markup) # Run command and return response
63
- markup.slice! "!"
64
- @logger.debug { "Execute markup=#{markup}" }
65
- contents = run(markup)
66
- else # The file is relative or it was passed as a parameter to an include and was not noticed before, e.g. @file='{{include.file}}'
67
- @logger.debug { "Catchall start @file=#{@file}, markup=#{markup}, path=#{path}" }
68
- file = render_variable(context)
69
- markup = file if file
70
- markup = expand_env(markup)
71
- markup = sanitize_parameter(markup)
72
- if /\A\//.match(markup) # Absolute path
73
- path = markup
74
- elsif /\A\!/.match(markup)
75
- markup.slice! "!"
76
- @logger.debug { "Execute markup=#{markup}" }
77
- contents = run(markup)
78
- elsif /\A~/.match(markup) # Relative path to user's home directory?
79
- markup.slice! "~/"
80
- path = File.join(ENV['HOME'], markup)
81
- else # Relative path
82
- site = context.registers[:site]
83
- source = File.expand_path(site.config['source']) # website root directory
84
- path = File.join(source, markup) # Fully qualified path of include file from relative path
85
- end
86
- @logger.debug { "Catchall end markup=#{markup}, path=#{path}" }
87
- end
88
- render_completion(context, path, contents)
66
+ render_completion(path, contents)
67
+ # rescue StandardError => e
68
+ # raise FlexibleIncludeError, e.message.red, [] # Suppress stack trace
89
69
  end
90
70
 
91
71
  private
92
72
 
93
- def escape_html?(context)
94
- do_not_escape = false
95
- if @params
96
- context["include"] = parse_params(context)
97
- @logger.debug { "context['include']['do_not_escape'] = #{context['include']['do_not_escape']}" }
98
- do_not_escape = context['include'].fetch('do_not_escape', 'false')
99
- @logger.debug { "do_not_escape=#{do_not_escape}" }
100
- @logger.debug { "do_not_escape=='false' = #{do_not_escape=='false'}" }
101
- end
102
- do_not_escape
103
- end
104
-
105
- def escape_html(string)
106
- string.gsub("{", "&#123;").gsub("}", "&#125;").gsub("<", "&lt;")
107
- end
108
-
109
- def expand_env(str)
110
- str.gsub(/\$([a-zA-Z_][a-zA-Z0-9_]*)|\${\g<1>}|%\g<1>%/) { ENV[$1] }
111
- end
112
-
113
- # Grab file read opts in the context
114
- def file_read_opts(context)
115
- context.registers[:site].file_read_opts
116
- end
117
-
118
- def parse_params(context)
119
- params = {}
120
- markup = @params
121
-
122
- while (match = VALID_SYNTAX.match(markup))
123
- markup = markup[match.end(0)..-1]
124
-
125
- value = if match[2]
126
- match[2].gsub(%r!\\"!, '"')
127
- elsif match[3]
128
- match[3].gsub(%r!\\'!, "'")
129
- elsif match[4]
130
- context[match[4]]
131
- end
132
-
133
- params[match[1]] = value
134
- end
135
- params
136
- end
137
-
138
73
  def read_file(file)
139
74
  File.read(file)
140
75
  end
@@ -145,72 +80,37 @@ class FlexibleInclude < Liquid::Tag
145
80
  false
146
81
  end
147
82
 
148
- def render_completion(context, path, contents)
149
- begin
150
- contents = read_file(path) unless contents
151
- rescue StandardError => e
152
- puts "flexible_include.rb error: #{e.message}".red
153
- $stderr.reopen(IO::NULL)
154
- $stdout.reopen(IO::NULL)
155
- exit
156
- end
157
- escaped_contents = escape_html?(context) ? escape_html(contents) : contents
158
- context.stack do # Temporarily push a new local scope onto the variable stack
159
- begin
160
- partial = Liquid::Template.parse(escaped_contents) # Type Liquid::Template
161
- rescue StandardError => e
162
- puts "flexible_include.rb error: #{e.message}".red
163
- $stderr.reopen(IO::NULL)
164
- $stdout.reopen(IO::NULL)
165
- exit
166
- end
167
-
168
- begin
169
- partial.render!(context)
170
- rescue Liquid::Error => e
171
- e.template_name = path
172
- e.markup_context = "included " if e.markup_context.nil?
173
- raise e
174
- end
175
- end
176
- end
177
-
178
- # @return setvalue of 'file' variable if defined
179
- def render_variable(context)
180
- if @file.match VARIABLE_SYNTAX
181
- partial = context.registers[:site]
182
- .liquid_renderer
183
- .file("(variable)")
184
- .parse(@file)
185
- partial.render!(context)
186
- end
83
+ def render_completion(path, contents)
84
+ contents ||= read_file(path)
85
+ contents2 = @do_not_escape ? contents : JekyllTagHelper.escape_html(contents)
86
+ @pre ? wrap_in_pre(path, contents2) : contents2
187
87
  end
188
88
 
189
89
  def run(cmd)
190
- %x[ #{cmd} ].chomp
191
- end
192
-
193
- # strip leading and trailing quotes if present
194
- def sanitize_parameter(parameter)
195
- parameter.strip.gsub(/\A'|'\Z/, '').strip if parameter
196
- end
197
-
198
- def valid_include_file?(path, dir, safe)
199
- !outside_site_source?(path, dir, safe) && File.file?(path)
200
- end
201
-
202
- def outside_site_source?(path, dir, safe)
203
- safe && !realpath_prefixed_with?(path, dir)
204
- end
205
-
206
- def could_not_locate_message(file, includes_dirs, safe)
207
- message = "Could not locate the included file '#{file}' in any of "\
208
- "#{includes_dirs}. Ensure it exists in one of those directories and"
209
- message + if safe
210
- " is not a symlink as those are not allowed in safe mode."
211
- else
212
- ", if it is a symlink, does not point outside your site source."
213
- end
90
+ @logger.debug { "Executing filename=#{cmd}" }
91
+ %x[#{cmd}].chomp
92
+ end
93
+
94
+ PREFIX = "<button class='copyBtn' data-clipboard-target="
95
+ SUFFIX = "title='Copy to clipboard'><img src='/assets/images/clippy.svg' alt='Copy to clipboard' style='width: 13px'></button>"
96
+
97
+ def wrap_in_pre(path, content)
98
+ basename = File.basename(path)
99
+ label_or_href = if @download
100
+ label = @label_specified ? @label : basename
101
+ <<~END_HREF
102
+ <a href='data:text/plain;charset=UTF-8,#{basename}' download='#{basename}'
103
+ title='Click on the file name to download the file'>#{label}</a>
104
+ END_HREF
105
+ else
106
+ @label_specified ? @label : basename
107
+ end
108
+ pre_id = "id#{SecureRandom.hex 6}"
109
+ copy_button = @copy_button ? "#{PREFIX}'##{pre_id}'#{SUFFIX}" : ""
110
+ <<~END_PRE
111
+ <div class="codeLabel">#{label_or_href}</div>
112
+ <pre data-lt-active="false" class="maxOneScreenHigh copyContainer" id="#{pre_id}">#{copy_button}#{content}</pre>
113
+ END_PRE
214
114
  end
215
115
  end
216
116
 
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "shellwords"
4
+
5
+ class JekyllTagHelper
6
+ attr_reader :argv, :liquid_context, :logger, :params, :tag_name
7
+
8
+ def self.escape_html(string)
9
+ string.gsub("{", "&#123;").gsub("}", "&#125;").gsub("<", "&lt;")
10
+ end
11
+
12
+ # Expand environment variable references
13
+ def self.expand_env(str)
14
+ str.gsub(/\$([a-zA-Z_][a-zA-Z0-9_]*)|\${\g<1>}|%\g<1>%/) { ENV[Regexp.last_match(1)] }
15
+ end
16
+
17
+ # strip leading and trailing quotes if present
18
+ def self.remove_quotes(string)
19
+ string.strip.gsub(/\A'|\A"|'\Z|"\Z/, '').strip if string
20
+ end
21
+
22
+ def initialize(tag_name, markup, logger)
23
+ @tag_name = tag_name
24
+ @argv = Shellwords.split(markup)
25
+ @keys_values = KeyValueParser.new.parse(@argv) # Hash[Symbol, String|Boolean]
26
+ @logger = logger
27
+ @logger.debug { "@keys_values='#{@keys_values}'" }
28
+ end
29
+
30
+ def delete_parameter(name)
31
+ @params.delete(name)
32
+ @argv.delete_if { |x| x.start_with? name }
33
+ @keys_values.delete(name.to_sym)
34
+ end
35
+
36
+ # @return if parameter was specified, returns value and removes it from the available tokens
37
+ def parameter_specified?(name)
38
+ value = @keys_values[name.to_sym]
39
+ delete_parameter(name)
40
+ value
41
+ end
42
+
43
+ PREDEFINED_SCOPE_KEYS = [:include, :page].freeze
44
+
45
+ # Finds variables defined in an invoking include, or maybe somewhere else
46
+ # @return variable value or nil
47
+ def dereference_include_variable(name)
48
+ @liquid_context.scopes.each do |scope|
49
+ next if PREDEFINED_SCOPE_KEYS.include? scope.keys.first
50
+
51
+ value = scope[name]
52
+ return value if value
53
+ end
54
+ nil
55
+ end
56
+
57
+ # @return value of variable, or the empty string
58
+ def dereference_variable(name)
59
+ @liquid_context[name] || # Finds variables named like 'include.my_variable', found in @liquid_context.scopes.first
60
+ @page[name] || # Finds variables named like 'page.my_variable'
61
+ dereference_include_variable(name) ||
62
+ ""
63
+ end
64
+
65
+ # Sets @params by replacing any Liquid variable names with their values
66
+ def liquid_context=(context)
67
+ @liquid_context = context
68
+ @params = @keys_values.map { |k, _v| lookup_variable(k) }
69
+ end
70
+
71
+ def lookup_variable(symbol)
72
+ string = symbol.to_s
73
+ return string unless string.start_with?("{{") && string.end_with?("}}")
74
+
75
+ dereference_variable(string.delete_prefix("{{").delete_suffix("}}"))
76
+ end
77
+
78
+ def page
79
+ @liquid_context.registers[:page]
80
+ end
81
+ end
metadata CHANGED
@@ -1,14 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jekyll_flexible_include
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.4
4
+ version: 2.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Slinn
8
+ - Tan Nhu
9
+ - Maarten Brakkee
8
10
  autorequire:
9
11
  bindir: exe
10
12
  cert_chain: []
11
- date: 2022-04-06 00:00:00.000000000 Z
13
+ date: 2022-04-13 00:00:00.000000000 Z
12
14
  dependencies:
13
15
  - !ruby/object:Gem::Dependency
14
16
  name: jekyll
@@ -85,6 +87,7 @@ files:
85
87
  - jekyll_flexible_include_plugin.gemspec
86
88
  - lib/flexible_include.rb
87
89
  - lib/flexible_include/version.rb
90
+ - lib/jekyll_tag_helper.rb
88
91
  homepage: https://www.mslinn.com/blog/2020/10/03/jekyll-plugins.html#flexibleInclude
89
92
  licenses:
90
93
  - MIT