jekyll_plugin_support 1.0.2 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +22 -1
- data/README.md +358 -29
- data/jekyll_plugin_support.gemspec +11 -10
- data/lib/block/jekyll_plugin_support_block.rb +30 -12
- data/lib/error/jekyll_custom_error.rb +3 -3
- data/lib/error/jekyll_plugin_error_handling.rb +1 -1
- data/lib/helper/jekyll_plugin_helper.rb +2 -2
- data/lib/helper/jekyll_plugin_helper_class.rb +6 -1
- data/lib/jekyll_plugin_support/jekyll_plugin_support_class.rb +58 -23
- data/lib/jekyll_plugin_support/version.rb +1 -1
- data/lib/jekyll_plugin_support.rb +1 -1
- data/lib/tag/jekyll_plugin_support_tag.rb +25 -11
- data/spec/liquid_variable_parsing_spec.rb +2 -2
- metadata +3 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b54badeb565b69fb6839140b7ce7b340d6a6663c226a3f7cb8728df2e0f61b2e
|
4
|
+
data.tar.gz: f74acdbe3c4d99561dead976deb36c4ff477f06dac7783a0ef918df901a71a53
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d3deaa658d05e5f9cf629ba10a337f9b864465462a362d1d4670eaa3afff32c78b04cbc974a17fb9afd9fbac1392a2e4c58c1e0fbbd40a145ac9c4076b5a741a
|
7
|
+
data.tar.gz: 910ca35d862324baac1eb5c627662f4f4dac01e5966a06ad9c071bf1354800458ff81f16e260375680845d7062ee9dc7c41c63ab994f4d2630ad56eacbe8bb51
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,26 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
## 1.1.0 / 2025-02-07
|
4
|
+
|
5
|
+
* Now replaces include and layout variables with their values
|
6
|
+
* Renamed `@helper.markup` to `@helper.argument_string`
|
7
|
+
* Improved `nil` handling throughout
|
8
|
+
* Added the **Debug Demo production** launch configuration to debug the demo website in production mode
|
9
|
+
* Added the `bin/release_port` script that kills hung processes being debugged
|
10
|
+
* Added the `cleanDemo` task for the **Debug Demo production** and **Debug Demo development** tasks
|
11
|
+
* Many minor improvements to the demo.
|
12
|
+
* `JekyllSupport::JekyllPluginHelper::register` now accepts a `quiet` option, to suppress the signon message.
|
13
|
+
Use it like this:
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
JekyllPluginHelper.register(self, 'tag_name', quiet: true)
|
17
|
+
```
|
18
|
+
|
19
|
+
|
20
|
+
## 1.0.3 / 2024-08-19
|
21
|
+
|
22
|
+
* Still fussing with error handling
|
23
|
+
|
3
24
|
|
4
25
|
## 1.0.2 / 2024-08-19
|
5
26
|
|
@@ -10,7 +31,7 @@
|
|
10
31
|
|
11
32
|
```ruby
|
12
33
|
rescue DemoInlineTagError => e # jekyll_plugin_support handles StandardError
|
13
|
-
@logger.error e.logger_message
|
34
|
+
@logger.error { e.logger_message }
|
14
35
|
exit! 1 if @die_on_demo_tag_error
|
15
36
|
|
16
37
|
e.html_message
|
data/README.md
CHANGED
@@ -1,13 +1,17 @@
|
|
1
1
|
# `jekyll_plugin_support` [](https://badge.fury.io/rb/jekyll_plugin_support)
|
2
2
|
|
3
|
-
|
3
|
+
After writing over two dozen Jekyll plugins, I distilled the common code into `Jekyll_plugin_support`.
|
4
|
+
This F/OSS Ruby gem facilitates writing and testing Jekyll plugins and handles the standard housekeeping that every Jekyll
|
5
|
+
inline and block tag plugin requires.
|
6
|
+
Logging, parsing arguments, obtaining references to site and page objects, etc. are all handled.
|
7
|
+
The result is faster Jekyll plugin writing with fewer bugs.
|
4
8
|
|
5
9
|
`Jekyll_plugin_support` can be used to create simple Jekyll plugins in
|
6
10
|
the `_plugins/` directory of your Jekyll project, or gem-based Jekyll plugins.
|
7
11
|
|
8
12
|
At present, only Jekyll tags and blocks are supported.
|
9
13
|
|
10
|
-
|
14
|
+
Public plugins that use `jekyll_plugin_support` include:
|
11
15
|
|
12
16
|
<ul style="columns: 2">
|
13
17
|
<li><a href='https://www.mslinn.com/jekyll_plugins/jekyll_all_collections'><code>jekyll_all_collections</code></a></li>
|
@@ -33,51 +37,70 @@ Jekyll plugin tags created from `jekyll_plugin_support` framework automatically
|
|
33
37
|
1. Boilerplate is removed, so you can focus on the required logic and output.
|
34
38
|
2. Arguments are parsed for keywords and name/value parameters.
|
35
39
|
3. Single or double quotes can be used for arguments and parameters.
|
36
|
-
4. Important variables are
|
40
|
+
4. Important variables are predefined.
|
37
41
|
5. Error handling is standardized, and includes an automatically defined error type
|
38
42
|
and corresponding CSS tag for each Jekyll tag.
|
39
|
-
6. Liquid variables
|
40
|
-
|
43
|
+
6. Jekyll and Liquid variables, including `layout`, `page` and `include` variables,
|
44
|
+
can be passed as parameters to tags, and used in the body of block tags.
|
45
|
+
7. Plugin registration is integrated, and important configuration details are reported during registration.
|
41
46
|
8. A custom logger is created for each tag, independent of the default Jekyll logger.
|
42
47
|
9. Variables can be defined in `_config.yml`, and optionally have different values for debug mode,
|
43
48
|
production mode and test mode.
|
44
49
|
10. An attribution message is available.
|
45
50
|
11. Draft pages are automatically detected.
|
46
|
-
|
47
|
-
|
51
|
+
12. A demonstration website is provided for easy testing of every plugin.
|
52
|
+
13. Visual Studio Code debugging is set up for the plugin code and the demo website.
|
53
|
+
14. Plugins can be subclassed.
|
54
|
+
15. [`Nugem`](https://mslinn.com/ruby/6800-nugem.html) can create working scaffolding for new plugins built
|
55
|
+
using `jekyll_plugin_support`.
|
48
56
|
|
49
57
|
|
50
58
|
## Installation
|
51
59
|
|
60
|
+
### For A Jekyll Website
|
61
|
+
|
52
62
|
`Jekyll_plugin_support` is packaged as a Ruby gem.
|
53
|
-
If
|
63
|
+
If you want to write a custom Jekyll plugin that will reside in a Jekyll project’s `_plugins` directory,
|
54
64
|
add the following line to your Jekyll plugin’s `Gemfile`.
|
55
65
|
|
56
66
|
```ruby
|
57
67
|
group :jekyll_plugins do
|
58
68
|
# ...
|
59
|
-
gem 'jekyll_plugin_support', '>=
|
69
|
+
gem 'jekyll_plugin_support', '>= 1.1.0'
|
60
70
|
# ...
|
61
71
|
end
|
62
72
|
```
|
63
73
|
|
64
|
-
|
74
|
+
Run the standard `jekyll_plugin_support` setup procedure:
|
75
|
+
|
76
|
+
```shell
|
77
|
+
$ bin/setup
|
78
|
+
```
|
79
|
+
|
80
|
+
|
81
|
+
### As a Gem Dependency
|
82
|
+
|
83
|
+
If your custom plugin will be packaged into a gem, add the following to your plugin’s `.gemspec`:
|
65
84
|
|
66
85
|
```ruby
|
67
86
|
Gem::Specification.new do |spec|
|
68
87
|
# ...
|
69
|
-
spec.add_dependency 'jekyll_plugin_support', '>=
|
88
|
+
spec.add_dependency 'jekyll_plugin_support', '>= 1.1.0'
|
70
89
|
# ...
|
71
90
|
end
|
72
91
|
```
|
73
92
|
|
74
|
-
Install the `jekyll_plugin_support`
|
93
|
+
Install the `jekyll_plugin_support` gem into your plugin project in the usual manner:
|
94
|
+
|
95
|
+
```shell
|
96
|
+
$ bundle
|
97
|
+
```
|
98
|
+
|
99
|
+
Copy the CSS classes from
|
100
|
+
[`demo/assets/css/jekyll_plugin_support.css`](demo/assets/css/jekyll_plugin_support.css)
|
101
|
+
to your Jekyll project’s CSS file.
|
75
102
|
|
76
|
-
```shell
|
77
|
-
$ bundle
|
78
|
-
```
|
79
103
|
|
80
|
-
Copy the CSS classes from `demo/assets/css/jekyll_plugin_support.css` to your Jekyll project’s CSS file.
|
81
104
|
|
82
105
|
|
83
106
|
## About `jekyll_plugin_support`
|
@@ -104,13 +127,21 @@ Instead, define a method called `render_impl`.
|
|
104
127
|
For inline tags, `render_impl` does not accept any parameters.
|
105
128
|
For block tags, a single parameter is required, which contains text passed from your block in the page.
|
106
129
|
|
107
|
-
Your implementation of render_impl can parse parameters passed to
|
130
|
+
Your implementation of render_impl can parse parameters passed to your tag, as described in
|
108
131
|
[Tag Parameter Parsing](http://mslinn.com/jekyll/10100-jekyll-plugin-background.html#params).
|
109
132
|
|
133
|
+
In addition, within <code>render_impl</code>,
|
134
|
+
the arguments passed to the tag will have been tokenized and parsed,
|
135
|
+
with Jekyll and Liquid variables substituted for their values,
|
136
|
+
and all the public Jekyll variables will be available as instance variables.
|
137
|
+
Error handling will also have been set up,
|
138
|
+
and access to your tag's entry within <code>_config.yml</code> will have been set up.
|
139
|
+
|
140
|
+
|
110
141
|
|
111
142
|
## General Usage
|
112
143
|
|
113
|
-
Please see the [`demo/`](demo/) project for a well-documented set of demonstration Jekyll plugins
|
144
|
+
Please see the [`demo/`](demo/) project for a well-documented set of demonstration Jekyll plugins built from `jekyll_plugin_support`.
|
114
145
|
Additional information is available [here](https://mslinn.com/jekyll/10200-jekyll-plugin-background.html) and the
|
115
146
|
[`jekyll_plugin_support`](https://www.mslinn.com/jekyll_plugins/jekyll_plugin_support.html) documentation.
|
116
147
|
|
@@ -141,7 +172,7 @@ because both `JekyllSupport` classes define this method.
|
|
141
172
|
|
142
173
|
Instead, define a method called `render_impl`.
|
143
174
|
For inline tags, `render_impl` does not accept any parameters.
|
144
|
-
For block tags, a single parameter is required, which
|
175
|
+
For block tags, a single parameter is required, which receives any text enclosed within your block by the website author.
|
145
176
|
|
146
177
|
|
147
178
|
## Predefined Plugin Variables
|
@@ -150,10 +181,12 @@ For block tags, a single parameter is required, which contains any text enclosed
|
|
150
181
|
|
151
182
|
* `@argument_string` Unparsed markup passed as a parameter to your block tag and inline tag.
|
152
183
|
|
184
|
+
* `@argv` returns any remaining tokens after `parameter_specified?` has been invoked.
|
185
|
+
|
153
186
|
* [`@attribution`](#subclass-attribution) Attribution markup
|
154
187
|
|
155
188
|
* [`@config`](https://docs.github.com/en/pages/setting-up-a-github-pages-site-with-jekyll/about-github-pages-and-jekyll#configuring-jekyll-in-your-github-pages-site)
|
156
|
-
[YAML](https://yaml.org/) Jekyll site configuration file
|
189
|
+
The [YAML](https://yaml.org/) Jekyll site configuration file
|
157
190
|
|
158
191
|
* [`@helper`](https://github.com/mslinn/jekyll_plugin_support/blob/master/lib/jekyll_plugin_helper.rb)
|
159
192
|
`JekyllPluginHelper` instance for your plugin.
|
@@ -165,7 +198,7 @@ For block tags, a single parameter is required, which contains any text enclosed
|
|
165
198
|
* [`@mode`](https://jekyllrb.com/docs/configuration/environments/)
|
166
199
|
Indicates `production`, `test` or `development` mode.
|
167
200
|
|
168
|
-
* [`@page`](https://jekyllrb.com/docs/variables/#page-variables) Page variables
|
201
|
+
* [`@page`](https://jekyllrb.com/docs/variables/#page-variables) `Jekyll::Page` variables
|
169
202
|
|
170
203
|
* [`@paginator`](https://jekyllrb.com/docs/variables/#page-variables) Pagination variables
|
171
204
|
|
@@ -322,7 +355,7 @@ call `@helper.remaining_markup` to obtain the remaining markup that was passed t
|
|
322
355
|
|
323
356
|
`jekyll_plugin_support` provides support for
|
324
357
|
[Liquid variables](https://shopify.github.io/liquid/tags/variable/)
|
325
|
-
to be defined in `_config.yml`, in a section called `
|
358
|
+
to be defined in `_config.yml`, in a section called `liquid_vars`.
|
326
359
|
These variables behave exactly like Liquid variables defined by `assign` and `capture` expressions,
|
327
360
|
except they are global in scope; these variables are available in every Jekyll web page.
|
328
361
|
|
@@ -339,7 +372,7 @@ Liquid variables defined in this manner are intended to be embedded in a webpage
|
|
339
372
|
They are can be used like any other Liquid variable.
|
340
373
|
|
341
374
|
|
342
|
-
|
375
|
+
## Variable Expansion
|
343
376
|
|
344
377
|
Jekyll expands Liquid variable references during the page rendering process.
|
345
378
|
Jekyll does not expand Liquid variable references passes as parameters to tag and block plugins, however.
|
@@ -444,7 +477,27 @@ Similarly, the letters `y` and `z` are pronounced {{y}} and {{z}}.
|
|
444
477
|
```
|
445
478
|
|
446
479
|
|
447
|
-
###
|
480
|
+
### Evaluating Include Variables
|
481
|
+
|
482
|
+
This information is only useful if a plugin might be executed from within an included file.
|
483
|
+
|
484
|
+
While Liquid handles regular variables, Jekyll has special handling for variables defined by include parameters.
|
485
|
+
For example, the following defines a variable in the `include` scope called `var1`
|
486
|
+
when processing the body of an included file:
|
487
|
+
|
488
|
+
```html
|
489
|
+
{% include myfile.html var1='value1' %}
|
490
|
+
```
|
491
|
+
|
492
|
+
You can obtain the value of this variable from the `render_impl` method of a
|
493
|
+
`JekyllSupport::JekyllTag` or `JekyllSupport::JekyllBlock` subclass as follows:
|
494
|
+
|
495
|
+
```ruby
|
496
|
+
@var1 = @scopes.first['include']&.[]('var1')
|
497
|
+
```
|
498
|
+
|
499
|
+
|
500
|
+
## Automatically Created Error Classes
|
448
501
|
|
449
502
|
`JekyllSupport::JekyllBlock` and `JekyllSupport::JekyllTag` subclasses
|
450
503
|
automatically create error classes, named after the subclass.
|
@@ -452,7 +505,8 @@ automatically create error classes, named after the subclass.
|
|
452
505
|
For example, if you create a `JekyllSupport::JekyllBlock` subclass called `DemoBlockTag`,
|
453
506
|
the automatically generated error class will be called `DemoBlockTagError`.
|
454
507
|
|
455
|
-
Although you could use it as you would any other error class, `JekyllPluginSupport`
|
508
|
+
Although you could use it as you would any other error class, `JekyllPluginSupport`
|
509
|
+
provides additional helper methods.
|
456
510
|
These methods fill in the page path and line number that caused the error, shorten the stack trace,
|
457
511
|
log an error message, and can be used to return an HTML-friendly version of the message to the web page.
|
458
512
|
|
@@ -482,7 +536,7 @@ Error class methods have been provided for standardized and convenient error han
|
|
482
536
|
* `html_message` - The same as `logger_message`, but constructed with HTML.
|
483
537
|
|
484
538
|
|
485
|
-
|
539
|
+
## Self-Reporting Upon Registration
|
486
540
|
|
487
541
|
When each tag is registered, it self-reports, for example:
|
488
542
|
|
@@ -514,6 +568,83 @@ If your tag or block plugin only needs access to the raw arguments passed from t
|
|
514
568
|
without tokenization, and you expect that the plugin might be invoked with large amounts of text,
|
515
569
|
derive your plugin from `JekyllBlockNoArgParsing` or `JekyllTagNoArgParsing`.
|
516
570
|
|
571
|
+
## Writing Plugins
|
572
|
+
|
573
|
+
The following minimal examples define `VERSION`,
|
574
|
+
which is important because `JekyllPluginHelper.register` logs that value when registering the plugin.
|
575
|
+
|
576
|
+
This is how you would define plugins in the `_plugins` directory
|
577
|
+
|
578
|
+
**Boilerplate for an inline tag plugin**
|
579
|
+
|
580
|
+
```ruby
|
581
|
+
require 'jekyll_plugin_support'
|
582
|
+
|
583
|
+
module Jekyll
|
584
|
+
class DemoTag < JekyllSupport::JekyllTag
|
585
|
+
VERSION = '0.1.0'.freeze
|
586
|
+
|
587
|
+
def render_impl
|
588
|
+
@helper.gem_file __FILE__ # Enables attribution; only works when plugin is a gem
|
589
|
+
# Your Jekyll plugin logic goes here
|
590
|
+
end
|
591
|
+
|
592
|
+
JekyllPluginHelper.register(self, 'demo_tag')
|
593
|
+
end
|
594
|
+
end
|
595
|
+
```
|
596
|
+
|
597
|
+
**Boilerplate for a tag block plugin**
|
598
|
+
|
599
|
+
```ruby
|
600
|
+
require 'jekyll_plugin_support'
|
601
|
+
|
602
|
+
module Jekyll
|
603
|
+
class DemoBlock < JekyllSupport::JekyllBlock
|
604
|
+
VERSION = '0.1.0'.freeze
|
605
|
+
|
606
|
+
def render_impl(text)
|
607
|
+
@helper.gem_file __FILE__ # Enables attribution; only works when plugin is a gem
|
608
|
+
# Your Jekyll plugin logic goes here
|
609
|
+
end
|
610
|
+
|
611
|
+
JekyllPluginHelper.register(self, 'demo_block')
|
612
|
+
end
|
613
|
+
end
|
614
|
+
```
|
615
|
+
|
616
|
+
If your plugin is packaged as a gem, then you might need to include `version.rb` into the plugin class.
|
617
|
+
For example, if your version module looks like this:
|
618
|
+
|
619
|
+
**lib/my_plugin/version.rb**:
|
620
|
+
|
621
|
+
```ruby
|
622
|
+
module MyPluginVersion
|
623
|
+
VERSION = '0.5.0'.freeze
|
624
|
+
end
|
625
|
+
```
|
626
|
+
|
627
|
+
Then your plugin can incorporate the VERSION constant into your plugin like this:
|
628
|
+
|
629
|
+
**lib/my_plugin.rb**:
|
630
|
+
|
631
|
+
```ruby
|
632
|
+
require 'jekyll_plugin_support'
|
633
|
+
require_relative 'my_plugin/version'
|
634
|
+
|
635
|
+
module Jekyll
|
636
|
+
class MyBlock < JekyllSupport::JekyllBlock
|
637
|
+
include MyPluginVersion
|
638
|
+
|
639
|
+
def render_impl(text)
|
640
|
+
@helper.gem_file __FILE__ # Enables attribution; only works when plugin is a gem
|
641
|
+
# Your code here
|
642
|
+
end
|
643
|
+
|
644
|
+
JekyllPluginHelper.register(self, 'demo_block')
|
645
|
+
end
|
646
|
+
end
|
647
|
+
```
|
517
648
|
|
518
649
|
## Attribution
|
519
650
|
|
@@ -583,7 +714,7 @@ An alternative attribution string can be specified properties can be output usin
|
|
583
714
|
{% my_tag attribution="Generated by the #{name} #{version} Jekyll plugin, written by #{author} #{date}" %}
|
584
715
|
```
|
585
716
|
|
586
|
-
## Subclassing
|
717
|
+
## Subclassing Plugins
|
587
718
|
|
588
719
|
Jekyll plugins created using `jekyll_plugin_support` are implemented as Ruby classes.
|
589
720
|
If you would like to create a version of an existing Jekyll plugin, you will need to subclass the plugin.
|
@@ -647,9 +778,203 @@ blah:
|
|
647
778
|
|
648
779
|
## Demonstration Plugins and Website
|
649
780
|
|
650
|
-
A demo / test website is provided in the `demo` directory.
|
781
|
+
A demo / test website is provided in the [`demo`](demo) directory.
|
651
782
|
It can be used to debug the plugin or to run freely.
|
652
783
|
|
784
|
+
### Examining the Demo Plugins
|
785
|
+
|
786
|
+
The following example plugins use
|
787
|
+
[Ruby’s squiggly heredoc operator](https://ruby-doc.org/core-2.5.0/doc/syntax/literals_rdoc.html#label-Here+Documents) (`<<~`).
|
788
|
+
The squiggly heredoc operator removes the outermost indentation.
|
789
|
+
This provides easy-to-read multiline text literals.
|
790
|
+
|
791
|
+
**demo/_plugins/demo_tag.rb**:
|
792
|
+
|
793
|
+
```ruby
|
794
|
+
require 'jekyll_plugin_support'
|
795
|
+
|
796
|
+
# Use the JekyllSupport module namespace so the self methods are automajically found
|
797
|
+
module JekyllSupport
|
798
|
+
DemoInlineTagError = JekyllSupport.define_error
|
799
|
+
|
800
|
+
class DemoTag < JekyllTag
|
801
|
+
VERSION = '0.1.2'.freeze
|
802
|
+
# JekyllSupport.redef_without_warning 'VERSION', '0.1.2'.freeze
|
803
|
+
|
804
|
+
def render_impl
|
805
|
+
@demo_tag_error = @helper.parameter_specified? 'raise_demo_tag_error'
|
806
|
+
@keyword1 = @helper.parameter_specified? 'keyword1'
|
807
|
+
@keyword2 = @helper.parameter_specified? 'keyword2'
|
808
|
+
@name1 = @helper.parameter_specified? 'name1'
|
809
|
+
@name2 = @helper.parameter_specified? 'name2'
|
810
|
+
@standard_error = @helper.parameter_specified? 'raise_standard_error'
|
811
|
+
|
812
|
+
if @tag_config
|
813
|
+
@die_on_demo_tag_error = @tag_config['die_on_demo_tag_error'] == true
|
814
|
+
@die_on_standard_error = @tag_config['die_on_standard_error'] == true
|
815
|
+
end
|
816
|
+
|
817
|
+
raise DemoInlineTagError, 'This DemoInlineTagError error is expected.' if @demo_tag_error
|
818
|
+
raise StandardError, 'This StandardError error is expected.' if @standard_error
|
819
|
+
|
820
|
+
# _infinity = 1 / 0 if @standard_error # Not required
|
821
|
+
|
822
|
+
output
|
823
|
+
rescue DemoInlineTagError => e # jekyll_plugin_support handles StandardError
|
824
|
+
@logger.error { e.logger_message }
|
825
|
+
exit! 1 if @die_on_demo_tag_error
|
826
|
+
|
827
|
+
e.html_message
|
828
|
+
end
|
829
|
+
|
830
|
+
private
|
831
|
+
|
832
|
+
def output
|
833
|
+
<<~END_OUTPUT
|
834
|
+
<pre># jekyll_plugin_support becomes able to perform variable substitution after this variable is defined.
|
835
|
+
# The value could be updated at a later stage, but no need to add that complexity unless there is a use case.
|
836
|
+
@argument_string="#{@argument_string}"
|
837
|
+
|
838
|
+
@helper.argv=
|
839
|
+
#{@helper.argv&.join("\n ")}
|
840
|
+
|
841
|
+
# Liquid variable name/value pairs
|
842
|
+
@helper.params=
|
843
|
+
#{@helper.params&.map { |k, v| "#{k}=#{v}" }&.join("\n ")}
|
844
|
+
|
845
|
+
# The keys_values property serves no purpose any more, consider it deprecated
|
846
|
+
@helper.keys_values=
|
847
|
+
#{(@helper.keys_values&.map { |k, v| "#{k}=#{v}" })&.join("\n ")}
|
848
|
+
|
849
|
+
@layout='#{@layout}'
|
850
|
+
@page.keys='#{@page.keys}'
|
851
|
+
|
852
|
+
remaining_markup='#{@helper.remaining_markup}'
|
853
|
+
|
854
|
+
@keyword1='#{@keyword1}'
|
855
|
+
@keyword2='#{@keyword2}'
|
856
|
+
@name1='#{@name1}'
|
857
|
+
@name2='#{@name2}'</pre>
|
858
|
+
END_OUTPUT
|
859
|
+
end
|
860
|
+
|
861
|
+
JekyllPluginHelper.register(self, 'demo_inline_tag')
|
862
|
+
end
|
863
|
+
end
|
864
|
+
```
|
865
|
+
|
866
|
+
**demo/_plugins/demo_block.rb**:
|
867
|
+
|
868
|
+
```ruby
|
869
|
+
require 'cgi'
|
870
|
+
require 'jekyll_plugin_support'
|
871
|
+
|
872
|
+
# Use the JekyllSupport module namespace so the self methods are automajically found
|
873
|
+
module JekyllSupport
|
874
|
+
DemoBlockError = JekyllSupport.define_error
|
875
|
+
|
876
|
+
class DemoBlock < JekyllBlock
|
877
|
+
VERSION = '0.1.2'.freeze
|
878
|
+
|
879
|
+
def render_impl(text)
|
880
|
+
@demo_block_error = @helper.parameter_specified? 'raise_demo_block_error'
|
881
|
+
@keyword1 = @helper.parameter_specified? 'keyword1'
|
882
|
+
@keyword2 = @helper.parameter_specified? 'keyword2'
|
883
|
+
@name1 = @helper.parameter_specified? 'name1'
|
884
|
+
@name2 = @helper.parameter_specified? 'name2'
|
885
|
+
@standard_error = @helper.parameter_specified? 'raise_standard_error'
|
886
|
+
|
887
|
+
if @tag_config
|
888
|
+
@die_on_demo_block_error = @tag_config['die_on_demo_block_error'] == true
|
889
|
+
@die_on_standard_error = @tag_config['die_on_standard_error'] == true
|
890
|
+
end
|
891
|
+
|
892
|
+
raise DemoBlockTagError, 'This DemoBlockTagError error is expected.' if @demo_block_error
|
893
|
+
raise StandardError, 'This StandardError error is expected.' if @standard_error
|
894
|
+
|
895
|
+
# _infinity = 1 / 0 if @standard_error # Not required
|
896
|
+
|
897
|
+
output text
|
898
|
+
rescue DemoBlockTagError => e # jekyll_plugin_support handles StandardError
|
899
|
+
@logger.error { e.logger_message }
|
900
|
+
exit! 1 if @die_on_demo_block_error
|
901
|
+
|
902
|
+
e.html_message
|
903
|
+
end
|
904
|
+
|
905
|
+
private
|
906
|
+
|
907
|
+
def output(text)
|
908
|
+
<<~END_OUTPUT
|
909
|
+
<pre>@helper.tag_name=#{@helper.tag_name}
|
910
|
+
|
911
|
+
@mode=#{@mode}
|
912
|
+
|
913
|
+
# jekyll_plugin_support becomes able to perform variable substitution after this variable is defined.
|
914
|
+
# The value could be updated at a later stage, but no need to add that complexity unless there is a use case.
|
915
|
+
@argument_string="#{@argument_string}"
|
916
|
+
|
917
|
+
@helper.argv=
|
918
|
+
#{@helper.argv&.join("\n ")}
|
919
|
+
|
920
|
+
# Liquid variable name/value pairs
|
921
|
+
@helper.params=
|
922
|
+
#{@helper.params&.map { |k, v| "#{k}=#{v}" }&.join("\n ")}
|
923
|
+
|
924
|
+
# The keys_values property serves no purpose any more, consider it deprecated
|
925
|
+
@helper.keys_values=
|
926
|
+
#{(@helper.keys_values&.map { |k, v| "#{k}=#{v}" })&.join("\n ")}
|
927
|
+
|
928
|
+
@helper.remaining_markup='#{@helper.remaining_markup}'
|
929
|
+
|
930
|
+
@envs=#{@envs.keys.sort.join(', ')}
|
931
|
+
|
932
|
+
@config['url']='#{@config['url']}'
|
933
|
+
|
934
|
+
@site.collection_names=#{@site.collection_names&.sort&.join(', ')}
|
935
|
+
|
936
|
+
@page['description']=#{@page['description']}
|
937
|
+
|
938
|
+
@page['path']=#{@page['path']}
|
939
|
+
|
940
|
+
@keyword1=#{@keyword1}
|
941
|
+
|
942
|
+
@keyword2=#{@keyword2}
|
943
|
+
|
944
|
+
@name1=#{@name1}
|
945
|
+
|
946
|
+
@name2=#{@name2}
|
947
|
+
|
948
|
+
text=#{text}</pre>
|
949
|
+
END_OUTPUT
|
950
|
+
end
|
951
|
+
|
952
|
+
JekyllPluginHelper.register(self, 'demo_block_tag')
|
953
|
+
end
|
954
|
+
end
|
955
|
+
```
|
956
|
+
|
957
|
+
The following is an example of no_arg_parsing optimization.
|
958
|
+
|
959
|
+
```ruby
|
960
|
+
require 'jekyll_plugin_support'
|
961
|
+
|
962
|
+
# Use the JekyllSupport module namespace so the self methods are automajically found
|
963
|
+
module JekyllSupport
|
964
|
+
class DemoTagNoArgs < JekyllTagNoArgParsing
|
965
|
+
VERSION = '0.1.0'.freeze
|
966
|
+
|
967
|
+
def render_impl
|
968
|
+
<<~END_OUTPUT
|
969
|
+
The raw arguments passed to this <code>DemoTagNoArgs</code> instance are:<br>
|
970
|
+
<code>#{@argument_string}</code>
|
971
|
+
END_OUTPUT
|
972
|
+
end
|
973
|
+
|
974
|
+
JekyllPluginHelper.register(self, 'demo_inline_tag_no_arg')
|
975
|
+
end
|
976
|
+
end
|
977
|
+
```
|
653
978
|
|
654
979
|
### Run Freely
|
655
980
|
|
@@ -668,6 +993,10 @@ It can be used to debug the plugin or to run freely.
|
|
668
993
|
|
669
994
|
1. Set breakpoints in Visual Studio Code.
|
670
995
|
|
996
|
+
2. Run the **Debug Demo development** or **Debug Demo production** launch configuration.
|
997
|
+
|
998
|
+
Alternatively, you can:
|
999
|
+
|
671
1000
|
2. Initiate a debug session from the command line by running the `demo/_bin/debug` script:
|
672
1001
|
|
673
1002
|
```shell
|
@@ -694,7 +1023,7 @@ It can be used to debug the plugin or to run freely.
|
|
694
1023
|
```
|
695
1024
|
|
696
1025
|
3. Once the `DEBUGGER: wait for debugger connection...` message appears,
|
697
|
-
run the Visual Studio Code launch configuration called
|
1026
|
+
run the Visual Studio Code launch configuration called **Attach with rdbg**.
|
698
1027
|
|
699
1028
|
4. View the generated website,
|
700
1029
|
which might be at [`http://localhost:4444`](http://localhost:4444),
|
@@ -3,12 +3,12 @@ require_relative 'lib/jekyll_plugin_support/version'
|
|
3
3
|
Gem::Specification.new do |spec|
|
4
4
|
github = 'https://github.com/mslinn/jekyll_plugin_support'
|
5
5
|
|
6
|
-
spec.bindir
|
7
|
-
spec.authors
|
8
|
-
spec.email
|
9
|
-
spec.files
|
6
|
+
spec.bindir = 'exe'
|
7
|
+
spec.authors = ['Mike Slinn']
|
8
|
+
spec.email = ['mslinn@mslinn.com']
|
9
|
+
spec.files = Dir['.rubocop.yml', 'LICENSE.*', 'Rakefile', '{lib,spec}/**/*', '*.gemspec', '*.md']
|
10
10
|
spec.homepage = 'https://www.mslinn.com/jekyll_plugins/jekyll_plugin_support.html'
|
11
|
-
spec.license
|
11
|
+
spec.license = 'MIT'
|
12
12
|
spec.metadata = {
|
13
13
|
'allowed_push_host' => 'https://rubygems.org',
|
14
14
|
'bug_tracker_uri' => "#{github}/issues",
|
@@ -16,17 +16,18 @@ Gem::Specification.new do |spec|
|
|
16
16
|
'homepage_uri' => spec.homepage,
|
17
17
|
'source_code_uri' => github,
|
18
18
|
}
|
19
|
-
spec.name
|
19
|
+
spec.name = 'jekyll_plugin_support'
|
20
|
+
spec.platform = Gem::Platform::RUBY
|
20
21
|
spec.post_install_message = <<~END_MESSAGE
|
21
22
|
|
22
23
|
Thanks for installing #{spec.name}!
|
23
24
|
|
24
25
|
END_MESSAGE
|
25
|
-
spec.require_paths
|
26
|
+
spec.require_paths = ['lib']
|
26
27
|
spec.required_ruby_version = '>= 2.6.0'
|
27
|
-
spec.summary
|
28
|
-
spec.test_files
|
29
|
-
spec.version
|
28
|
+
spec.summary = 'Provides a framework for writing and testing Jekyll plugins'
|
29
|
+
spec.test_files = spec.files.grep %r{^(test|spec|features)/}
|
30
|
+
spec.version = JekyllPluginSupportVersion::VERSION
|
30
31
|
|
31
32
|
spec.add_dependency 'facets'
|
32
33
|
spec.add_dependency 'jekyll', '>= 3.5.0'
|
@@ -8,16 +8,28 @@ module JekyllSupport
|
|
8
8
|
# See https://github.com/Shopify/liquid/wiki/Liquid-for-Programmers#create-your-own-tags
|
9
9
|
# @param tag_name [String] the name of the tag, which we usually know.
|
10
10
|
# @param argument_string [String] the arguments passed to the tag, as a single string.
|
11
|
-
# @param parse_context [Liquid::ParseContext]
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
11
|
+
# @param parse_context [Liquid::ParseContext] contains the following attributes:
|
12
|
+
# @depth might have the value 0
|
13
|
+
# @error_mode might have the value `:strict`
|
14
|
+
# @line_number duplicates @ptions[:line_number]
|
15
|
+
# @locale duplicates @ptions[:locale]
|
16
|
+
# @options is a hash with the following two keys that holds Liquid options:
|
17
|
+
# :locale is a Liquid::I18n object, used to display localized error messages on Liquid built-in tags and filters.
|
18
|
+
# :line_number is the line number containing the plugin invocation.
|
19
|
+
# See https://github.com/Shopify/liquid/wiki/Liquid-for-Programmers#create-your-own-tags
|
20
|
+
# @partial Boolean, unclear what this indicates
|
21
|
+
# @template_options Replicates @options
|
22
|
+
# @trim_whitespace might have the value `false`
|
23
|
+
# @warnings array
|
16
24
|
# @return [void]
|
17
25
|
def initialize(tag_name, markup, parse_context)
|
18
26
|
super
|
19
27
|
@tag_name = tag_name
|
20
|
-
|
28
|
+
raise JekyllPluginSupportError, "markup is a #{markup.class} with value '#{markup}'." unless markup.instance_of? String
|
29
|
+
|
30
|
+
# Lookup variable names with values in markup in render because site and config are not available here
|
31
|
+
@argument_string = markup # Replace variable names with values in markup in render because site and config are not available here
|
32
|
+
|
21
33
|
@logger = PluginMetaLogger.instance.new_logger(self, PluginMetaLogger.instance.config)
|
22
34
|
@logger.debug { "#{self.class}: respond_to?(:no_arg_parsing) #{respond_to?(:no_arg_parsing) ? 'yes' : 'no'}." }
|
23
35
|
@helper = JekyllPluginHelper.new tag_name, markup, @logger, respond_to?(:no_arg_parsing)
|
@@ -36,11 +48,11 @@ module JekyllSupport
|
|
36
48
|
# Defines @config, @envs, @mode, @page and @site
|
37
49
|
# @return [String]
|
38
50
|
def render(liquid_context)
|
39
|
-
@helper.liquid_context = JekyllSupport.
|
51
|
+
@helper.liquid_context = JekyllSupport.inject_config_vars liquid_context # modifies liquid_context
|
40
52
|
text = super # Liquid variable values in content are looked up and substituted
|
41
53
|
|
42
54
|
@envs = liquid_context.environments.first
|
43
|
-
@page = liquid_context.registers[:page]
|
55
|
+
@page = liquid_context.registers[:page]
|
44
56
|
@scopes = liquid_context.scopes
|
45
57
|
@site = liquid_context.registers[:site]
|
46
58
|
|
@@ -51,6 +63,7 @@ module JekyllSupport
|
|
51
63
|
|
52
64
|
set_error_context
|
53
65
|
|
66
|
+
# @envs.keys are :content, :highlighter_prefix, :highlighter_suffix, :jekyll, :layout, :page, :paginator, :site, :theme
|
54
67
|
@layout = @envs[:layout]
|
55
68
|
@paginator = @envs[:paginator]
|
56
69
|
@theme = @envs[:theme]
|
@@ -58,18 +71,23 @@ module JekyllSupport
|
|
58
71
|
env = @config['env']
|
59
72
|
@mode = env&.key?('JEKYLL_ENV') ? env['JEKYLL_ENV'] : 'development'
|
60
73
|
|
61
|
-
@helper.
|
74
|
+
@argument_string = JekyllSupport.lookup_liquid_variables @logger, @helper.liquid_context, @argument_string.to_s.strip
|
75
|
+
@helper.reinitialize @argument_string.to_s.strip
|
62
76
|
|
63
77
|
@attribution = @helper.parameter_specified?('attribution') || false unless @no_arg_parsing
|
64
78
|
@logger.debug { "@keys_values='#{@keys_values}'" }
|
65
79
|
|
66
|
-
|
67
|
-
@
|
80
|
+
# @argument_string = JekyllSupport.lookup_liquid_variables @logger, liquid_context, @argument_string # Is this redundant?
|
81
|
+
# @argument_string.strip! # Is this redundant?
|
82
|
+
# @helper.reinitialize @argument_string # Is this redundant?
|
68
83
|
|
69
84
|
render_impl(text)
|
70
85
|
rescue StandardError => e
|
71
86
|
e.shorten_backtrace
|
72
|
-
|
87
|
+
file_name = e.backtrace[0]&.split(':')&.first
|
88
|
+
in_file_name = "in '#{file_name}' " if file_name
|
89
|
+
of_page = "of '#{@page['path']}'" if @page
|
90
|
+
@logger.error { "#{e.class} on line #{@line_number} #{of_page} while processing #{tag_name} #{in_file_name}- #{e.message}" }
|
73
91
|
binding.pry if @pry_on_standard_error # rubocop:disable Lint/Debugger
|
74
92
|
raise e if @die_on_standard_error
|
75
93
|
|
@@ -16,14 +16,14 @@ module JekyllSupport
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def calling_file
|
19
|
-
file_fq, _line_number, _extra = backtrace[0]
|
19
|
+
file_fq, _line_number, _extra = backtrace[0]&.split(':')
|
20
20
|
file_fq
|
21
21
|
end
|
22
22
|
|
23
23
|
# @return HTML <div> tag with class set to the snake_case version of the error class name.
|
24
24
|
def html_message
|
25
25
|
shorten_backtrace
|
26
|
-
path, line_number, _caller = backtrace[1]
|
26
|
+
path, line_number, _caller = backtrace[1]&.split(':')
|
27
27
|
<<~END_MSG
|
28
28
|
<div class='#{error_name.snakecase}'>
|
29
29
|
#{self.class} raised in #{calling_file} while processing line #{line_number} (after front matter) of #{path}
|
@@ -35,7 +35,7 @@ module JekyllSupport
|
|
35
35
|
def logger_message
|
36
36
|
shorten_backtrace
|
37
37
|
kaller = caller(1..1).first
|
38
|
-
path, line_number, _caller = backtrace[1]
|
38
|
+
path, line_number, _caller = backtrace[1]&.split(':')
|
39
39
|
<<~END_MSG
|
40
40
|
#{error_name} raised in #{kaller} while processing line #{line_number} (after front matter) of #{path}
|
41
41
|
#{message}
|
@@ -34,7 +34,7 @@ module JekyllSupportError
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def maybe_reraise_error(error, throw_error: true)
|
37
|
-
fmsg =
|
37
|
+
fmsg = format_error_message "#{error.class}: #{error.message.strip}"
|
38
38
|
@logger.error { fmsg }
|
39
39
|
return "<span class='jekyll_plugin_support_error'>#{fmsg}</span>" unless throw_error
|
40
40
|
|
@@ -23,7 +23,7 @@ module JekyllSupport
|
|
23
23
|
@tag_name = tag_name
|
24
24
|
@logger = logger
|
25
25
|
@no_arg_parsing = no_arg_parsing
|
26
|
-
@
|
26
|
+
@argument_string = markup
|
27
27
|
rescue StandardError => e
|
28
28
|
e.shorten_backtrace
|
29
29
|
@logger.error { e.message }
|
@@ -42,7 +42,7 @@ module JekyllSupport
|
|
42
42
|
|
43
43
|
def reinitialize(markup)
|
44
44
|
# @keys_values was a Hash[Symbol, String|Boolean] but now it is Hash[String, String|Boolean]
|
45
|
-
@
|
45
|
+
@argument_string = markup
|
46
46
|
if @no_arg_parsing
|
47
47
|
define_singleton_method(:argv) { warn_fetch :argv }
|
48
48
|
define_singleton_method(:keys_values) { warn_fetch :keys_values }
|
@@ -55,7 +55,10 @@ module JekyllSupport
|
|
55
55
|
END_MSG
|
56
56
|
end
|
57
57
|
|
58
|
-
|
58
|
+
# @param klass [Class] class instance to register
|
59
|
+
# @param tag_name [String] name of plugin defined by klass to register as
|
60
|
+
# @param quiet [Boolean] suppress registration message if truthy
|
61
|
+
def self.register(klass, tag_name, quiet: false)
|
59
62
|
abort("Error: The #{tag_name} plugin does not define VERSION") \
|
60
63
|
unless klass.const_defined?(:VERSION)
|
61
64
|
|
@@ -67,6 +70,8 @@ module JekyllSupport
|
|
67
70
|
klass.ancestors.include?(JekyllSupport::JekyllTag))
|
68
71
|
|
69
72
|
Liquid::Template.register_tag(tag_name, klass)
|
73
|
+
return if quiet
|
74
|
+
|
70
75
|
msg = generate_message(klass, tag_name, version)
|
71
76
|
PluginMetaLogger.instance.info { msg }
|
72
77
|
end
|
@@ -39,23 +39,21 @@ module JekyllSupport
|
|
39
39
|
END_MSG
|
40
40
|
end
|
41
41
|
|
42
|
-
#
|
43
|
-
# Modifies liquid_context in the caller
|
42
|
+
# Inject variable definitions from _config.yml into liquid_context
|
43
|
+
# Modifies liquid_context.scopes in the caller
|
44
44
|
# (call by object reference, see https://stackoverflow.com/a/1872159/553865)
|
45
45
|
# @return modified liquid_context
|
46
46
|
# See README.md#configuration-variable-definitions
|
47
47
|
# See demo/variables.html
|
48
|
-
def self.
|
49
|
-
# TODO: Modify a deep clone? Do I dare?
|
48
|
+
def self.inject_config_vars(liquid_context)
|
50
49
|
site = liquid_context.registers[:site]
|
51
50
|
|
52
51
|
plugin_variables = site.config['liquid_vars']
|
53
|
-
return liquid_context unless plugin_variables
|
54
52
|
|
55
53
|
scope = liquid_context.scopes.last
|
56
54
|
|
57
55
|
env = site.config['env']
|
58
|
-
mode = env&.key?('JEKYLL_ENV') ? env['JEKYLL_ENV'] : 'development'
|
56
|
+
@mode = env&.key?('JEKYLL_ENV') ? env['JEKYLL_ENV'] : 'development'
|
59
57
|
|
60
58
|
# Set default values
|
61
59
|
plugin_variables&.each do |name, value|
|
@@ -63,7 +61,7 @@ module JekyllSupport
|
|
63
61
|
end
|
64
62
|
|
65
63
|
# Override with environment-specific values
|
66
|
-
plugin_variables[mode
|
64
|
+
plugin_variables&.[](@mode)&.each do |name, value|
|
67
65
|
scope[name] = value if value.instance_of? String
|
68
66
|
end
|
69
67
|
|
@@ -85,34 +83,71 @@ module JekyllSupport
|
|
85
83
|
# Modifies a clone of markup_original so variable references are replaced by their values
|
86
84
|
# @param markup_original to be cloned
|
87
85
|
# @return modified markup_original
|
88
|
-
def self.lookup_liquid_variables(liquid_context, markup_original)
|
86
|
+
def self.lookup_liquid_variables(logger, liquid_context, markup_original)
|
89
87
|
markup = markup_original.clone
|
90
|
-
page
|
88
|
+
page = liquid_context.registers[:page]
|
91
89
|
envs = liquid_context.environments.first
|
92
90
|
layout = envs[:layout]
|
93
91
|
|
94
|
-
|
92
|
+
markup = process_layout_variables logger, layout, markup
|
93
|
+
markup = process_page_variables logger, page, markup
|
94
|
+
liquid_context.scopes&.each do |scope|
|
95
|
+
markup = process_included_variables logger, scope, markup
|
96
|
+
markup = process_liquid_variables logger, scope, markup
|
97
|
+
end
|
98
|
+
markup
|
99
|
+
rescue StandardError => e
|
100
|
+
logger.error { e.full_message }
|
101
|
+
end
|
102
|
+
|
103
|
+
def self.process_included_variables(logger, scope, markup)
|
104
|
+
scope['include']&.each do |name, value|
|
105
|
+
if value.nil?
|
106
|
+
value = ''
|
107
|
+
logger.warn { "include.#{name} is undefined." }
|
108
|
+
end
|
109
|
+
markup.gsub!("{{include.#{name}}}", value)
|
110
|
+
end
|
111
|
+
markup
|
112
|
+
rescue StandardError => e
|
113
|
+
logger.error { e.full_message }
|
114
|
+
end
|
115
|
+
|
116
|
+
def self.process_layout_variables(logger, layout, markup)
|
95
117
|
layout&.each do |name, value|
|
118
|
+
if value.nil?
|
119
|
+
value = ''
|
120
|
+
logger.warn { "layout.#{value} is undefined." }
|
121
|
+
end
|
96
122
|
markup.gsub!("{{layout.#{name}}}", value.to_s)
|
97
123
|
end
|
124
|
+
markup
|
125
|
+
rescue StandardError => e
|
126
|
+
logger.error { e.full_message }
|
127
|
+
end
|
98
128
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
markup.gsub!("{{page.#{key}}}", page[key].to_s)
|
129
|
+
# Process assigned, captured and injected variables
|
130
|
+
def self.process_liquid_variables(logger, scope, markup)
|
131
|
+
scope&.each do |name, value|
|
132
|
+
next if name.nil?
|
133
|
+
|
134
|
+
value = '' if value.nil?
|
135
|
+
markup.gsub!("{{#{name}}}", value&.to_s)
|
107
136
|
end
|
137
|
+
markup
|
138
|
+
rescue StandardError => e
|
139
|
+
logger.error { e.full_message }
|
140
|
+
end
|
108
141
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
142
|
+
def self.process_page_variables(logger, page, markup)
|
143
|
+
page&.each_key do |key|
|
144
|
+
next if %w[content excerpt next previous output].include? key # Skip problem attributes
|
145
|
+
|
146
|
+
markup.gsub!("{{page.#{key}}}", page[key].to_s)
|
114
147
|
end
|
115
148
|
markup
|
149
|
+
rescue StandardError => e
|
150
|
+
logger.error { e.full_message }
|
116
151
|
end
|
117
152
|
|
118
153
|
def self.warn_short_trace(logger, error)
|
@@ -9,18 +9,28 @@ module JekyllSupport
|
|
9
9
|
# See https://github.com/Shopify/liquid/wiki/Liquid-for-Programmers#create-your-own-tags
|
10
10
|
# @param tag_name [String] the name of the tag, which we usually know.
|
11
11
|
# @param argument_string [String] the arguments passed to the tag, as a single string.
|
12
|
-
# @param parse_context [Liquid::ParseContext]
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
12
|
+
# @param parse_context [Liquid::ParseContext] contains the following attributes:
|
13
|
+
# @depth might have the value 0
|
14
|
+
# @error_mode might have the value `:strict`
|
15
|
+
# @line_number duplicates @ptions[:line_number]
|
16
|
+
# @locale duplicates @ptions[:locale]
|
17
|
+
# @options is a hash with the following two keys that holds Liquid options:
|
18
|
+
# :locale is a Liquid::I18n object, used to display localized error messages on Liquid built-in tags and filters.
|
19
|
+
# :line_number is the line number containing the plugin invocation.
|
20
|
+
# See https://github.com/Shopify/liquid/wiki/Liquid-for-Programmers#create-your-own-tags
|
21
|
+
# @partial Boolean, unclear what this indicates
|
22
|
+
# @template_options Replicates @options
|
23
|
+
# @trim_whitespace might have the value `false`
|
24
|
+
# @warnings array
|
17
25
|
# @return [void]
|
18
26
|
def initialize(tag_name, markup, parse_context)
|
19
27
|
super
|
20
28
|
@tag_name = tag_name
|
21
29
|
raise JekyllPluginSupportError, "markup is a #{markup.class} with value '#{markup}'." unless markup.instance_of? String
|
22
30
|
|
23
|
-
|
31
|
+
# Vars in plugin parameters cannot be replaced yet
|
32
|
+
@argument_string = markup.to_s # Lookup variable names with values in markup in render because site and config are not available here
|
33
|
+
|
24
34
|
@logger = PluginMetaLogger.instance.new_logger(self, PluginMetaLogger.instance.config)
|
25
35
|
@logger.debug { "#{self.class}: respond_to?(:no_arg_parsing) #{respond_to?(:no_arg_parsing) ? 'yes' : 'no'}." }
|
26
36
|
@helper = JekyllPluginHelper.new(tag_name, @argument_string, @logger, respond_to?(:no_arg_parsing))
|
@@ -33,7 +43,7 @@ module JekyllSupport
|
|
33
43
|
def render(liquid_context)
|
34
44
|
return if @helper.excerpt_caller
|
35
45
|
|
36
|
-
@helper.liquid_context = JekyllSupport.
|
46
|
+
@helper.liquid_context = JekyllSupport.inject_config_vars liquid_context # modifies liquid_context
|
37
47
|
|
38
48
|
@envs = liquid_context.environments.first
|
39
49
|
@page = liquid_context.registers[:page]
|
@@ -55,8 +65,12 @@ module JekyllSupport
|
|
55
65
|
env = @config['env']
|
56
66
|
@mode = env&.key?('JEKYLL_ENV') ? env['JEKYLL_ENV'] : 'development'
|
57
67
|
|
58
|
-
|
59
|
-
@helper.reinitialize
|
68
|
+
@argument_string = JekyllSupport.lookup_liquid_variables @logger, @helper.liquid_context, @argument_string.to_s.strip
|
69
|
+
@helper.reinitialize @argument_string.to_s.strip
|
70
|
+
|
71
|
+
# @argument_string = JekyllSupport.lookup_liquid_variables @logger, liquid_context, @argument_string # Is this redundant?
|
72
|
+
# @argument_string.strip! # Is this redundant?
|
73
|
+
# @helper.reinitialize @argument_string # Is this redundant?
|
60
74
|
|
61
75
|
render_impl
|
62
76
|
rescue StandardError => e
|
@@ -64,13 +78,13 @@ module JekyllSupport
|
|
64
78
|
file_name = e.backtrace[0]&.split(':')&.first
|
65
79
|
in_file_name = "in '#{file_name}' " if file_name
|
66
80
|
of_page = "of '#{@page['path']}'" if @page
|
67
|
-
@logger.error { "#{e.class} on line #{@line_number} #{of_page}while processing #{tag_name} #{in_file_name}- #{e.message}" }
|
81
|
+
@logger.error { "#{e.class} on line #{@line_number} #{of_page} while processing #{tag_name} #{in_file_name}- #{e.message}" }
|
68
82
|
binding.pry if @pry_on_standard_error # rubocop:disable Lint/Debugger
|
69
83
|
raise e if @die_on_standard_error
|
70
84
|
|
71
85
|
<<~END_MSG
|
72
86
|
<div class='standard_error'>
|
73
|
-
#{e.class} on line #{@line_number}
|
87
|
+
#{e.class} on line #{@line_number} #{of_page} while processing #{tag_name} #{in_file_name} - #{JekyllPluginHelper.remove_html_tags e.message}
|
74
88
|
</div>
|
75
89
|
END_MSG
|
76
90
|
end
|
@@ -8,12 +8,12 @@ class LiquidVariableParsing
|
|
8
8
|
def variable_replace(str, scopes)
|
9
9
|
result = str.clone
|
10
10
|
match_data_list = str.to_enum(:scan, /{{[a-z_][a-zA-Z_0-9]*}}/).map { Regexp.last_match }.reverse
|
11
|
-
match_data_list
|
11
|
+
match_data_list&.each do |md|
|
12
12
|
from = md.begin(0)
|
13
13
|
to = md.end(0) - 1
|
14
14
|
ref = str[from..to]
|
15
15
|
name = ref[2..-3]
|
16
|
-
scopes
|
16
|
+
scopes&.each do |scope|
|
17
17
|
value = scope.key?(name) ? scope[name] : ref
|
18
18
|
# puts "str=#{str}; from=#{from}; to=#{to}; name=#{name} value=#{value}"
|
19
19
|
result[from..to] = value
|
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jekyll_plugin_support
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Slinn
|
8
|
-
autorequire:
|
9
8
|
bindir: exe
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 2025-02-07 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
13
12
|
- !ruby/object:Gem::Dependency
|
14
13
|
name: facets
|
@@ -80,7 +79,6 @@ dependencies:
|
|
80
79
|
- - ">="
|
81
80
|
- !ruby/object:Gem::Version
|
82
81
|
version: '0'
|
83
|
-
description:
|
84
82
|
email:
|
85
83
|
- mslinn@mslinn.com
|
86
84
|
executables: []
|
@@ -140,8 +138,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
140
138
|
- !ruby/object:Gem::Version
|
141
139
|
version: '0'
|
142
140
|
requirements: []
|
143
|
-
rubygems_version: 3.
|
144
|
-
signing_key:
|
141
|
+
rubygems_version: 3.6.3
|
145
142
|
specification_version: 4
|
146
143
|
summary: Provides a framework for writing and testing Jekyll plugins
|
147
144
|
test_files:
|