trmnl-liquid 0.4.0 → 0.5.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
- checksums.yaml.gz.sig +0 -0
- data/LICENSE.txt +21 -0
- data/README.md +130 -0
- data/lib/trmnl/liquid/fallback.rb +30 -25
- data/lib/trmnl/liquid/filters.rb +107 -134
- data/lib/trmnl/liquid/memory_system.rb +25 -0
- data/lib/trmnl/liquid/rails_helpers.rb +13 -0
- data/lib/trmnl/liquid/template_tag.rb +25 -14
- data/lib/trmnl/liquid.rb +29 -26
- data/trmnl-liquid.gemspec +12 -15
- data.tar.gz.sig +0 -0
- metadata +46 -44
- metadata.gz.sig +0 -0
- data/lib/trmnl/liquid/file_system.rb +0 -21
- data/lib/trmnl/liquid/version.rb +0 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f138875593bd56d979eed237763c5e72a4dc5fdc3df60c35d6eeadffcb72bc87
|
|
4
|
+
data.tar.gz: 71bf4b24705129b781c295e3acf17fd70620df8773be3b15a1d4eaee7f734771
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c0bff6334290e4eb2cbba125672faa0b9a63707bae29112e3d439f95401b259db3f3d0e8525f9c9fb61a77e1d38fe70b6bb4211929358f042f3ce59133a50a39
|
|
7
|
+
data.tar.gz: 909f77f15b1c3cc2027e295f97da11145978e0e80fcb3d46a5ca901b9fb17cc80cc6100eb729747ba21859122cefb10a52cdf23f4e4c75f9a425aae9d6a7e19d
|
checksums.yaml.gz.sig
ADDED
|
Binary file
|
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Rockwell Schrock
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# TRMNL Liquid
|
|
2
|
+
|
|
3
|
+
A set of Liquid filters and tags used to render custom plugins for [TRMNL](https://trmnl.com).
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
Install the gem and add to the application's Gemfile by executing:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
bundle add trmnl-liquid
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
If bundler is not being used to manage dependencies, install the gem by executing:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
gem install trmnl-liquid
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Setup
|
|
20
|
+
|
|
21
|
+
For [Rails](https://rubyonrails.org) folks, you'll need to load the Rails feature but you *only need to do this once* (typically via an initializer). Example:
|
|
22
|
+
|
|
23
|
+
``` ruby
|
|
24
|
+
TRMNL::Liquid.load :rails
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
The above will load the Rails i18n support and other functionality for you to use this gem within a Rails application. For any application that isn't using Rails, we have fallbacks that should be sufficient but we're working to close that gap further. For instance, here's how you can configure this gem within a [Hanami](https://hanamirb.org) application as a *provider*:
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
``` ruby
|
|
31
|
+
Hanami.app.register_provider :liquid, namespace: true do
|
|
32
|
+
prepare { require "trmnl/liquid" }
|
|
33
|
+
|
|
34
|
+
start do
|
|
35
|
+
default = TRMNL::Liquid.new { |environment| environment.error_mode = :strict }
|
|
36
|
+
|
|
37
|
+
renderer = lambda do |template, data, environment: default|
|
|
38
|
+
Liquid::Template.parse(template, environment:).render data
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
register :default, renderer
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
If you ignore the provider logic and only focus on the body of the provider `start` life cyle, this can provide inspiration on how you can configure this gem further and use within your own application regardless of web stack.
|
|
47
|
+
|
|
48
|
+
## Usage
|
|
49
|
+
|
|
50
|
+
Functionality is achieved by parsing a template with the option `{ environment: TRMNL::Liquid.new }`. The environment concept was introduced in [v5.6.0](https://github.com/Shopify/liquid/releases/tag/v5.6.0) of the `liquid` gem as a safer alternative to global registration of tags, filters, and so on. See [lib/trmnl/liquid/filters.rb](lib/trmnl/liquid/filters.rb) for the currently-supported filters.
|
|
51
|
+
|
|
52
|
+
```ruby
|
|
53
|
+
require "trmnl/liquid"
|
|
54
|
+
|
|
55
|
+
markup = "Hello {{ count | number_with_delimiter }} people!"
|
|
56
|
+
environment = TRMNL::Liquid.new # same arguments as Liquid::Environment.build
|
|
57
|
+
template = Liquid::Template.parse(markup, environment: environment)
|
|
58
|
+
rendered = template.render(count: 1337)
|
|
59
|
+
# => "Hello 1,337 people!"
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
Additionally, the `{% template %}` tag defines reusable chunks of markup:
|
|
64
|
+
|
|
65
|
+
```liquid
|
|
66
|
+
{% template say_hello %}
|
|
67
|
+
<h1>Why hello there, {{ name }}!</h1>
|
|
68
|
+
{% endtemplate %}
|
|
69
|
+
|
|
70
|
+
{% render "say_hello", name: "General Kenobi" %}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
For more information, check out our help guides:
|
|
74
|
+
|
|
75
|
+
- [Liquid 101](https://help.trmnl.com/en/articles/10671186-liquid-101)
|
|
76
|
+
- [Advanced Liquid](https://help.trmnl.com/en/articles/10693981-advanced-liquid)
|
|
77
|
+
- [Custom Plugin Filters](https://help.trmnl.com/en/articles/10347358-custom-plugin-filters)
|
|
78
|
+
|
|
79
|
+
### Rails (optional)
|
|
80
|
+
|
|
81
|
+
The following is optional and only works for Rails applications. Once again, you'll want to enable Rails support by adding the following as an initializer:
|
|
82
|
+
|
|
83
|
+
``` ruby
|
|
84
|
+
TRMNL::Liquid.load :rails
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Then you can include internationalization and/or number and text formatting as described below.
|
|
88
|
+
|
|
89
|
+
#### Internationalization
|
|
90
|
+
|
|
91
|
+
Some filter functions (e.g. `number_to_currency`, `l_word`, and `l_date`) require translations provided by the [rails-i18n](https://rubygems.org/gems/rails-i18n) and [trmnl-i18n](https://rubygems.org/gems/trmnl-i18n) gems. These dependencies are optional, and if missing will fall back to default behavior. If you want to internationalize, also include these gems:
|
|
92
|
+
|
|
93
|
+
```ruby
|
|
94
|
+
# optional peer dependencies
|
|
95
|
+
gem "rails-i18n", "~> 8.0"
|
|
96
|
+
gem "trmnl-i18n", github: "usetrmnl/trmnl-i18n", branch: "main" # recommended for the latest changes
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
#### Number and Text Formatting
|
|
100
|
+
|
|
101
|
+
This gem does not _require_ ActionView, but it will leverage ActionView helpers if they are available.
|
|
102
|
+
|
|
103
|
+
```ruby
|
|
104
|
+
# optional peer dependency
|
|
105
|
+
gem "actionview", "~> 8.0"
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Development
|
|
109
|
+
|
|
110
|
+
After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
|
111
|
+
|
|
112
|
+
To publish, run the following:
|
|
113
|
+
|
|
114
|
+
``` ruby
|
|
115
|
+
# Step 0: You only need to do this once.
|
|
116
|
+
bundle install gemsmith
|
|
117
|
+
|
|
118
|
+
# Step 1: Edit the version number in trmnl-liquid.gemspec and update it to your desired version.
|
|
119
|
+
|
|
120
|
+
# Step 2: Publish the new version.
|
|
121
|
+
gemsmith --publish
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Contributing
|
|
125
|
+
|
|
126
|
+
Enhancements, bugs, code reviews, and other requests are welcome via [GitHub](https://github.com/usetrmnl/trmnl-liquid).
|
|
127
|
+
|
|
128
|
+
## License
|
|
129
|
+
|
|
130
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
|
@@ -1,17 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module TRMNL
|
|
2
4
|
module Liquid
|
|
3
5
|
# library-native formatting functions that don't rely on ActionView helpers
|
|
4
6
|
module Fallback
|
|
5
|
-
|
|
7
|
+
module_function
|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
+
# :reek:TooManyStatements
|
|
10
|
+
# rubocop:todo Metrics/MethodLength
|
|
11
|
+
def number_with_delimiter number, delimiter, separator
|
|
12
|
+
value = number.to_s
|
|
9
13
|
|
|
10
14
|
# return early if it's not a simple numeric-like string
|
|
11
|
-
return
|
|
15
|
+
return value unless value.match?(/\A-?\d+(\.\d+)?\z/)
|
|
12
16
|
|
|
13
|
-
integer, fractional =
|
|
14
|
-
negative = integer.start_with?
|
|
17
|
+
integer, fractional = value.split "."
|
|
18
|
+
negative = integer.start_with? "-"
|
|
15
19
|
integer = integer[1..] if negative
|
|
16
20
|
|
|
17
21
|
integer_with_delimiters = integer.reverse.scan(/\d{1,3}/).join(delimiter).reverse
|
|
@@ -23,39 +27,40 @@ module TRMNL
|
|
|
23
27
|
integer_with_delimiters
|
|
24
28
|
end
|
|
25
29
|
end
|
|
30
|
+
# rubocop:enable Metrics/MethodLength
|
|
26
31
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
32
|
+
# rubocop:disable Metrics/ParameterLists
|
|
33
|
+
def number_to_currency number, unit, delimiter, separator, precision
|
|
34
|
+
result = number_with_delimiter number, delimiter, separator
|
|
35
|
+
dollars, cents = result.split separator
|
|
30
36
|
|
|
31
37
|
if precision <= 0
|
|
32
38
|
"#{unit}#{dollars}"
|
|
33
39
|
else
|
|
34
|
-
cents = cents.to_s[0..(precision - 1)].ljust
|
|
40
|
+
cents = cents.to_s[0..(precision - 1)].ljust precision, "0"
|
|
35
41
|
"#{unit}#{dollars}#{separator}#{cents}"
|
|
36
42
|
end
|
|
37
43
|
end
|
|
44
|
+
# rubocop:enable Metrics/ParameterLists
|
|
45
|
+
|
|
46
|
+
# :reek:TooManyStatements
|
|
47
|
+
def ordinalize number
|
|
48
|
+
return "#{number}th" if (11..13).cover? number % 100
|
|
38
49
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
when 1 then 'st'
|
|
46
|
-
when 2 then 'nd'
|
|
47
|
-
when 3 then 'rd'
|
|
48
|
-
else 'th'
|
|
49
|
-
end
|
|
50
|
-
end
|
|
50
|
+
suffix = case number % 10
|
|
51
|
+
when 1 then "st"
|
|
52
|
+
when 2 then "nd"
|
|
53
|
+
when 3 then "rd"
|
|
54
|
+
else "th"
|
|
55
|
+
end
|
|
51
56
|
|
|
52
57
|
"#{number}#{suffix}"
|
|
53
58
|
end
|
|
54
59
|
|
|
55
|
-
def pluralize
|
|
60
|
+
def pluralize count, singular, plural
|
|
56
61
|
plural ||= "#{singular}s"
|
|
57
|
-
count == 1 ? "1 #{singular}"
|
|
62
|
+
count == 1 ? "1 #{singular}" : "#{count} #{plural}"
|
|
58
63
|
end
|
|
59
64
|
end
|
|
60
65
|
end
|
|
61
|
-
end
|
|
66
|
+
end
|
data/lib/trmnl/liquid/filters.rb
CHANGED
|
@@ -1,225 +1,198 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
require
|
|
4
|
-
require
|
|
5
|
-
require
|
|
6
|
-
require
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
# optional
|
|
11
|
-
%w[
|
|
12
|
-
i18n
|
|
13
|
-
action_view
|
|
14
|
-
active_support/core_ext/integer/inflections
|
|
15
|
-
].each do |lib|
|
|
16
|
-
begin
|
|
17
|
-
require lib
|
|
18
|
-
rescue LoadError
|
|
19
|
-
nil
|
|
20
|
-
end
|
|
21
|
-
end
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "json"
|
|
4
|
+
require "redcarpet"
|
|
5
|
+
require "rqrcode"
|
|
6
|
+
require "securerandom"
|
|
7
|
+
require "tzinfo"
|
|
8
|
+
|
|
9
|
+
require_relative "fallback"
|
|
22
10
|
|
|
23
11
|
module TRMNL
|
|
24
12
|
module Liquid
|
|
13
|
+
# rubocop:todo Metrics/ModuleLength
|
|
25
14
|
module Filters
|
|
26
|
-
def append_random(
|
|
27
|
-
"#{var}#{SecureRandom.hex(2)}"
|
|
28
|
-
end
|
|
15
|
+
def append_random(value) = "#{value}#{SecureRandom.hex 2}"
|
|
29
16
|
|
|
30
|
-
def days_ago
|
|
31
|
-
|
|
32
|
-
tzinfo.now.to_date - num.to_i
|
|
17
|
+
def days_ago value, timezone = "Etc/UTC"
|
|
18
|
+
TZInfo::Timezone.get(timezone).now.to_date - value.to_i
|
|
33
19
|
end
|
|
34
20
|
|
|
35
|
-
def group_by(collection, key)
|
|
36
|
-
collection.group_by { |obj| obj[key] }
|
|
37
|
-
end
|
|
21
|
+
def group_by(collection, key) = collection.group_by { it[key] }
|
|
38
22
|
|
|
39
|
-
|
|
23
|
+
# :reek:ControlParameter
|
|
24
|
+
# rubocop:todo Metrics/ParameterLists
|
|
25
|
+
def find_by collection, key, value, fallback = nil
|
|
40
26
|
collection.find { |obj| obj[key] == value } || fallback
|
|
41
27
|
end
|
|
28
|
+
# rubocop:enable Metrics/ParameterLists
|
|
42
29
|
|
|
43
|
-
def markdown_to_html
|
|
44
|
-
markdown ||=
|
|
45
|
-
renderer = Redcarpet::Render::HTML.new
|
|
46
|
-
service = Redcarpet::Markdown.new
|
|
47
|
-
service.render
|
|
30
|
+
def markdown_to_html markdown
|
|
31
|
+
markdown ||= ""
|
|
32
|
+
renderer = Redcarpet::Render::HTML.new _render_options = {}
|
|
33
|
+
service = Redcarpet::Markdown.new renderer, _extensions = {}
|
|
34
|
+
service.render markdown
|
|
48
35
|
end
|
|
49
36
|
|
|
50
|
-
def number_with_delimiter
|
|
51
|
-
if
|
|
52
|
-
|
|
37
|
+
def number_with_delimiter number, delimiter = ",", separator = "."
|
|
38
|
+
if RailsHelpers.respond_to? :number_with_delimiter
|
|
39
|
+
RailsHelpers.number_with_delimiter number, delimiter: delimiter, separator: separator
|
|
53
40
|
else
|
|
54
|
-
Fallback.number_with_delimiter
|
|
41
|
+
Fallback.number_with_delimiter number, delimiter, separator
|
|
55
42
|
end
|
|
56
43
|
end
|
|
57
44
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
45
|
+
# :reek:TooManyStatements
|
|
46
|
+
# rubocop:todo Metrics/ParameterLists
|
|
47
|
+
def number_to_currency number,
|
|
48
|
+
unit_or_locale = "$",
|
|
49
|
+
delimiter = ",",
|
|
50
|
+
separator = ".",
|
|
51
|
+
precision = 2
|
|
52
|
+
if RailsHelpers.respond_to? :number_to_currency
|
|
53
|
+
cur_switcher = with_i18n :unit do |i18n|
|
|
61
54
|
i18n.available_locales.include?(unit_or_locale.to_sym) ? :locale : :unit
|
|
62
55
|
end
|
|
63
|
-
opts = {
|
|
64
|
-
|
|
56
|
+
opts = {delimiter:, separator:, precision:}.merge cur_switcher => unit_or_locale
|
|
57
|
+
RailsHelpers.number_to_currency(number, **opts)
|
|
65
58
|
else
|
|
66
|
-
Fallback.number_to_currency
|
|
59
|
+
Fallback.number_to_currency number, unit_or_locale, delimiter, separator, precision
|
|
67
60
|
end
|
|
68
61
|
end
|
|
62
|
+
# rubocop:enable Metrics/ParameterLists
|
|
69
63
|
|
|
70
|
-
def l_word
|
|
71
|
-
with_i18n("custom_plugins.#{word}")
|
|
72
|
-
i18n.t("custom_plugins.#{word}", locale: locale)
|
|
73
|
-
end
|
|
64
|
+
def l_word word, locale
|
|
65
|
+
with_i18n("custom_plugins.#{word}") { |i18n| i18n.t "custom_plugins.#{word}", locale: }
|
|
74
66
|
end
|
|
75
67
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
68
|
+
# :reek:FeatureEnvy
|
|
69
|
+
def l_date value, format, locale = "en"
|
|
70
|
+
with_i18n value.to_s do |i18n|
|
|
71
|
+
format = format.to_sym unless format.include? "%"
|
|
72
|
+
i18n.l to_time(value), format:, locale:
|
|
80
73
|
end
|
|
81
74
|
end
|
|
82
75
|
|
|
83
|
-
def map_to_i(collection)
|
|
84
|
-
collection.map(&:to_i)
|
|
85
|
-
end
|
|
76
|
+
def map_to_i(collection) = collection.map(&:to_i)
|
|
86
77
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
78
|
+
# :reek:FeatureEnvy
|
|
79
|
+
# rubocop:todo Style/OptionHash
|
|
80
|
+
def pluralize singular, count, options = {}
|
|
81
|
+
plural = options["plural"]
|
|
82
|
+
locale = options["locale"] || with_i18n(nil, &:locale) || "en"
|
|
90
83
|
|
|
91
|
-
if
|
|
92
|
-
|
|
84
|
+
if RailsHelpers.respond_to? :pluralize
|
|
85
|
+
RailsHelpers.pluralize count, singular, plural: plural, locale: locale
|
|
93
86
|
else
|
|
94
|
-
Fallback.pluralize
|
|
87
|
+
Fallback.pluralize count, singular, plural
|
|
95
88
|
end
|
|
96
89
|
end
|
|
90
|
+
# rubocop:enable Style/OptionHash
|
|
97
91
|
|
|
98
|
-
def json(
|
|
99
|
-
JSON.generate(obj)
|
|
100
|
-
end
|
|
92
|
+
def json(value) = JSON.generate value
|
|
101
93
|
|
|
102
|
-
def parse_json(
|
|
103
|
-
JSON.parse(obj)
|
|
104
|
-
end
|
|
94
|
+
def parse_json(value) = JSON.parse value
|
|
105
95
|
|
|
106
96
|
def sample(array) = array.sample
|
|
107
97
|
|
|
98
|
+
# :reek:TooManyStatements
|
|
108
99
|
# source: https://github.com/jekyll/jekyll/blob/40ac06ed3e95325a07868dd2ac419e409af823b6/lib/jekyll/filters.rb#L209
|
|
109
|
-
def where_exp
|
|
110
|
-
return input unless input.respond_to?
|
|
100
|
+
def where_exp input, variable, expression
|
|
101
|
+
return input unless input.respond_to? :select
|
|
111
102
|
|
|
112
|
-
input = input.values if input.is_a?
|
|
103
|
+
input = input.values if input.is_a? Hash
|
|
104
|
+
condition = parse_condition expression
|
|
113
105
|
|
|
114
|
-
condition = parse_condition(expression)
|
|
115
106
|
@context.stack do
|
|
116
107
|
input.select do |object|
|
|
117
108
|
@context[variable] = object
|
|
118
|
-
condition.evaluate
|
|
109
|
+
condition.evaluate @context
|
|
119
110
|
end
|
|
120
111
|
end || []
|
|
121
112
|
end
|
|
122
113
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
date.strftime(strftime_exp.gsub('<<ordinal_day>>', ordinal_day))
|
|
114
|
+
# :reek:FeatureEnvy
|
|
115
|
+
def ordinalize value, strftime_format
|
|
116
|
+
time = to_time value
|
|
117
|
+
day = time.day
|
|
118
|
+
ordinal_day = day.respond_to?(:ordinalize) ? day.ordinalize : Fallback.ordinalize(day)
|
|
119
|
+
|
|
120
|
+
time.strftime strftime_format.gsub("<<ordinal_day>>", ordinal_day)
|
|
133
121
|
end
|
|
134
122
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
level =
|
|
123
|
+
# rubocop:todo Metrics/MethodLength
|
|
124
|
+
def qr_code data, size = 11, level = ""
|
|
125
|
+
level = "h" unless %w[l m q h].include? level.downcase
|
|
138
126
|
|
|
139
127
|
qrcode = RQRCode::QRCode.new(data, level:)
|
|
140
128
|
qrcode.as_svg(
|
|
141
|
-
color:
|
|
142
|
-
fill:
|
|
143
|
-
shape_rendering:
|
|
129
|
+
color: "000",
|
|
130
|
+
fill: "fff",
|
|
131
|
+
shape_rendering: "crispEdges",
|
|
144
132
|
module_size: size,
|
|
145
133
|
standalone: true,
|
|
146
134
|
use_path: true,
|
|
147
135
|
svg_attributes: {
|
|
148
|
-
class:
|
|
136
|
+
class: "qr-code"
|
|
149
137
|
}
|
|
150
138
|
)
|
|
151
139
|
end
|
|
140
|
+
# rubocop:enable Metrics/MethodLength
|
|
152
141
|
|
|
153
142
|
private
|
|
154
143
|
|
|
155
|
-
def with_i18n
|
|
144
|
+
def with_i18n fallback
|
|
156
145
|
if defined?(::I18n)
|
|
157
|
-
|
|
146
|
+
yield ::I18n
|
|
158
147
|
else
|
|
159
148
|
fallback
|
|
160
149
|
end
|
|
161
150
|
end
|
|
162
151
|
|
|
163
|
-
def
|
|
164
|
-
case
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
obj.to_datetime
|
|
169
|
-
when Time
|
|
170
|
-
DateTime.parse(obj.iso8601)
|
|
171
|
-
else
|
|
172
|
-
DateTime.parse(obj.to_s)
|
|
152
|
+
def to_time value
|
|
153
|
+
case value
|
|
154
|
+
when "now", "today" then Time.now
|
|
155
|
+
when Integer then Time.at(value)
|
|
156
|
+
else Time.parse value
|
|
173
157
|
end
|
|
174
158
|
end
|
|
175
159
|
|
|
176
|
-
def parse_condition
|
|
177
|
-
parser = ::Liquid::Parser.new
|
|
178
|
-
condition = parse_binary_comparison
|
|
160
|
+
def parse_condition expression
|
|
161
|
+
parser = ::Liquid::Parser.new expression
|
|
162
|
+
condition = parse_binary_comparison parser
|
|
179
163
|
|
|
180
|
-
parser.consume
|
|
164
|
+
parser.consume :end_of_string
|
|
181
165
|
condition
|
|
182
166
|
end
|
|
183
167
|
|
|
184
|
-
|
|
185
|
-
|
|
168
|
+
# :reek:TooManyStatements
|
|
169
|
+
# :reek:DuplicateMethodCall
|
|
170
|
+
def parse_binary_comparison parser
|
|
171
|
+
condition = parse_comparison parser
|
|
186
172
|
first_condition = condition
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
173
|
+
|
|
174
|
+
while (binary_operator = parser.id?("and") || parser.id?("or"))
|
|
175
|
+
child_condition = parse_comparison parser
|
|
176
|
+
condition.public_send binary_operator, child_condition
|
|
190
177
|
condition = child_condition
|
|
191
178
|
end
|
|
179
|
+
|
|
192
180
|
first_condition
|
|
193
181
|
end
|
|
194
182
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
183
|
+
# :reek:DuplicateMethodCall
|
|
184
|
+
def parse_comparison parser
|
|
185
|
+
left_operand = ::Liquid::Expression.parse parser.expression
|
|
186
|
+
operator = parser.consume? :comparison
|
|
198
187
|
|
|
199
188
|
# No comparison-operator detected. Initialize a Liquid::Condition using only left operand
|
|
200
|
-
return ::Liquid::Condition.new
|
|
189
|
+
return ::Liquid::Condition.new left_operand unless operator
|
|
201
190
|
|
|
202
191
|
# Parse what remained after extracting the left operand and the `:comparison` operator
|
|
203
192
|
# and initialize a Liquid::Condition object using the operands and the comparison-operator
|
|
204
|
-
::Liquid::Condition.new
|
|
205
|
-
end
|
|
206
|
-
|
|
207
|
-
class Helpers
|
|
208
|
-
%w[
|
|
209
|
-
::ActionView::Helpers::TextHelper
|
|
210
|
-
::ActionView::Helpers::NumberHelper
|
|
211
|
-
].each do |name|
|
|
212
|
-
begin
|
|
213
|
-
include Object.const_get(name)
|
|
214
|
-
rescue NameError
|
|
215
|
-
next
|
|
216
|
-
end
|
|
217
|
-
end
|
|
218
|
-
end
|
|
219
|
-
|
|
220
|
-
def helpers
|
|
221
|
-
@helpers ||= Helpers.new
|
|
193
|
+
::Liquid::Condition.new left_operand, operator, ::Liquid::Expression.parse(parser.expression)
|
|
222
194
|
end
|
|
223
195
|
end
|
|
196
|
+
# rubocop:enable Metrics/ModuleLength
|
|
224
197
|
end
|
|
225
198
|
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module TRMNL
|
|
4
|
+
module Liquid
|
|
5
|
+
# An in-memory file system for storing custom templates defined with {% template [name] %} tags.
|
|
6
|
+
class MemorySystem < ::Liquid::BlankFileSystem
|
|
7
|
+
def initialize
|
|
8
|
+
super
|
|
9
|
+
@templates = {}
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def register name, body
|
|
13
|
+
templates[name] = body
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def read_template_file name
|
|
17
|
+
templates[name] || fail(::Liquid::FileSystemError, "Template not found: #{name}.")
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
attr_reader :templates
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "action_view"
|
|
4
|
+
|
|
5
|
+
module TRMNL
|
|
6
|
+
module Liquid
|
|
7
|
+
# Defines Rails helpers for use in filters.
|
|
8
|
+
module RailsHelpers
|
|
9
|
+
extend ActionView::Helpers::TextHelper
|
|
10
|
+
extend ActionView::Helpers::NumberHelper
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -1,33 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module TRMNL
|
|
2
4
|
module Liquid
|
|
3
|
-
# The {% template [name] %} tag block is used in conjunction with InlineTemplatesFileSystem to
|
|
4
|
-
# custom templates within the context of the current Liquid template.
|
|
5
|
-
# templates in the "shared" markup content,
|
|
5
|
+
# The {% template [name] %} tag block is used in conjunction with InlineTemplatesFileSystem to
|
|
6
|
+
# allow users to define custom templates within the context of the current Liquid template.
|
|
7
|
+
# Generally speaking, they will define their own templates in the "shared" markup content,
|
|
8
|
+
# which is prepended to the individual screen templates before rendering.
|
|
6
9
|
class TemplateTag < ::Liquid::Block
|
|
7
|
-
|
|
10
|
+
NAME_PATTERN = %r(\A[a-zA-Z0-9_/]+\z)
|
|
8
11
|
|
|
9
|
-
def initialize
|
|
12
|
+
def initialize tag_name, markup, options
|
|
10
13
|
super
|
|
14
|
+
|
|
11
15
|
@name = markup.strip
|
|
16
|
+
@body = +""
|
|
12
17
|
end
|
|
13
18
|
|
|
14
|
-
def parse
|
|
15
|
-
|
|
19
|
+
def parse tokens
|
|
20
|
+
body.clear
|
|
21
|
+
|
|
16
22
|
while (token = tokens.shift)
|
|
17
23
|
break if token.strip == "{% endtemplate %}"
|
|
18
24
|
|
|
19
|
-
|
|
25
|
+
body << token
|
|
20
26
|
end
|
|
21
27
|
end
|
|
22
28
|
|
|
23
|
-
def render
|
|
24
|
-
unless
|
|
25
|
-
return "Liquid error: invalid template name #{
|
|
29
|
+
def render context
|
|
30
|
+
unless NAME_PATTERN.match? name
|
|
31
|
+
return "Liquid error: invalid template name #{name.inspect} - template names " \
|
|
32
|
+
"must contain only letters, numbers, underscores, and slashes"
|
|
26
33
|
end
|
|
27
34
|
|
|
28
|
-
context.registers[:file_system].register
|
|
29
|
-
|
|
35
|
+
context.registers[:file_system].register name, body.strip
|
|
36
|
+
""
|
|
30
37
|
end
|
|
38
|
+
|
|
39
|
+
private
|
|
40
|
+
|
|
41
|
+
attr_reader :name, :body
|
|
31
42
|
end
|
|
32
43
|
end
|
|
33
|
-
end
|
|
44
|
+
end
|
data/lib/trmnl/liquid.rb
CHANGED
|
@@ -1,36 +1,39 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
3
|
+
require "liquid"
|
|
4
|
+
require "trmnl/liquid/filters"
|
|
5
|
+
require "trmnl/liquid/memory_system"
|
|
6
|
+
require "trmnl/liquid/template_tag"
|
|
4
7
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
8
|
+
module TRMNL
|
|
9
|
+
# Main namespace.
|
|
10
|
+
module Liquid
|
|
11
|
+
def self.build_environment(...)
|
|
12
|
+
warn "`#{self.class}##{__method__}` is deprecated, use `new` instead.", category: :deprecated
|
|
13
|
+
new(...)
|
|
14
|
+
end
|
|
9
15
|
|
|
10
|
-
#
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
end
|
|
16
|
+
# :reek:TooManyStatements
|
|
17
|
+
def self.load key
|
|
18
|
+
case key
|
|
19
|
+
when :rails
|
|
20
|
+
require "trmnl/liquid/rails_helpers"
|
|
16
21
|
|
|
17
|
-
|
|
18
|
-
::TRMNL::I18n.load_locales
|
|
19
|
-
end
|
|
22
|
+
require "trmnl/i18n"
|
|
20
23
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
+
TRMNL::I18n.load_locales
|
|
25
|
+
path = Pathname Gem.loaded_specs["rails-i18n"].full_gem_path
|
|
26
|
+
::I18n.load_path += path.join("rails/locale").glob("*.yml")
|
|
27
|
+
else fail KeyError, "Unable to load extension due to invalid key: #{key.inspect}."
|
|
28
|
+
end
|
|
29
|
+
end
|
|
24
30
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
env.register_tag('template', TRMNL::Liquid::TemplateTag)
|
|
31
|
-
env.file_system = TRMNL::Liquid::FileSystem.new
|
|
32
|
-
yield(env) if block_given?
|
|
31
|
+
def self.new(file_system: TRMNL::Liquid::MemorySystem.new, **)
|
|
32
|
+
::Liquid::Environment.build(file_system:, **) do |environment|
|
|
33
|
+
environment.register_filter TRMNL::Liquid::Filters
|
|
34
|
+
environment.register_tag "template", TRMNL::Liquid::TemplateTag
|
|
35
|
+
yield environment if block_given?
|
|
33
36
|
end
|
|
34
37
|
end
|
|
35
38
|
end
|
|
36
|
-
end
|
|
39
|
+
end
|
data/trmnl-liquid.gemspec
CHANGED
|
@@ -1,17 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative "lib/trmnl/liquid/version"
|
|
4
|
-
|
|
5
3
|
Gem::Specification.new do |spec|
|
|
6
4
|
spec.name = "trmnl-liquid"
|
|
7
|
-
spec.version =
|
|
5
|
+
spec.version = "0.5.0"
|
|
8
6
|
spec.authors = ["TRMNL"]
|
|
9
|
-
spec.email = ["engineering@
|
|
7
|
+
spec.email = ["engineering@trmnl.com"]
|
|
10
8
|
spec.homepage = "https://github.com/usetrmnl/trmnl-liquid"
|
|
11
|
-
|
|
12
9
|
spec.summary = "Liquid templating engine for TRMNL plugins"
|
|
13
10
|
spec.license = "MIT"
|
|
14
|
-
spec.required_ruby_version = ">= 3.2.0"
|
|
15
11
|
|
|
16
12
|
spec.metadata = {
|
|
17
13
|
"bug_tracker_uri" => "https://github.com/usetrmnl/trmnl-liquid/issues",
|
|
@@ -22,15 +18,16 @@ Gem::Specification.new do |spec|
|
|
|
22
18
|
"source_code_uri" => "https://github.com/usetrmnl/trmnl-liquid"
|
|
23
19
|
}
|
|
24
20
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
spec.files = Dir["*.gemspec", "lib/**/*"]
|
|
28
|
-
spec.require_paths = ["lib"]
|
|
21
|
+
spec.signing_key = Gem.default_key_path
|
|
22
|
+
spec.cert_chain = [Gem.default_cert_path]
|
|
29
23
|
|
|
30
|
-
spec.
|
|
31
|
-
|
|
24
|
+
spec.required_ruby_version = ">= 4.0"
|
|
25
|
+
|
|
26
|
+
spec.add_dependency "liquid", "~> 5.11"
|
|
32
27
|
spec.add_dependency "redcarpet", "~> 3.6"
|
|
33
|
-
spec.add_dependency "rqrcode", "~> 3.
|
|
34
|
-
spec.add_dependency "
|
|
35
|
-
|
|
28
|
+
spec.add_dependency "rqrcode", "~> 3.2"
|
|
29
|
+
spec.add_dependency "tzinfo", "~> 2.0"
|
|
30
|
+
|
|
31
|
+
spec.extra_rdoc_files = Dir["README*", "LICENSE*"]
|
|
32
|
+
spec.files = Dir["*.gemspec", "lib/**/*"]
|
|
36
33
|
end
|
data.tar.gz.sig
ADDED
|
Binary file
|
metadata
CHANGED
|
@@ -1,42 +1,54 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: trmnl-liquid
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.5.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- TRMNL
|
|
8
8
|
bindir: bin
|
|
9
|
-
cert_chain:
|
|
9
|
+
cert_chain:
|
|
10
|
+
- |
|
|
11
|
+
-----BEGIN CERTIFICATE-----
|
|
12
|
+
MIIENjCCAp6gAwIBAgIBAjANBgkqhkiG9w0BAQsFADBBMQ8wDQYDVQQDDAZicm9v
|
|
13
|
+
a2UxGjAYBgoJkiaJk/IsZAEZFgphbGNoZW1pc3RzMRIwEAYKCZImiZPyLGQBGRYC
|
|
14
|
+
aW8wHhcNMjUwMzIyMTQ1NDE3WhcNMjYwMzIyMTQ1NDE3WjBBMQ8wDQYDVQQDDAZi
|
|
15
|
+
cm9va2UxGjAYBgoJkiaJk/IsZAEZFgphbGNoZW1pc3RzMRIwEAYKCZImiZPyLGQB
|
|
16
|
+
GRYCaW8wggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQCro8tj5/E1Hg88
|
|
17
|
+
f4qfiwPVd2zJQHvdYt4GHVvuHRRgx4HGhJuNp+4BId08RBn7V6V1MW6MY3kezRBs
|
|
18
|
+
M+7QOQ4b1xNLTvY7FYQB1wGK5a4x7TTokDrPYQxDB2jmsdDYCzVbIMrAvUfcecRi
|
|
19
|
+
khyGZCdByiiCl4fKv77P12tTT+NfsvXkLt/AYCGwjOUyGKTQ01Z6eC09T27GayPH
|
|
20
|
+
QQvIkakyFgcJtzSyGzs8bzK5q9u7wQ12MNTjJoXzW69lqp0oNvDylu81EiSUb5S6
|
|
21
|
+
QzzPxZBiRB1sgtbt1gUbVI262ZDq1gR+HxPFmp+Cgt7ZLIJZAtesQvtcMzseXpfn
|
|
22
|
+
hpmm0Sw22KGhRAy/mqHBRhDl5HqS1SJp2Ko3lcnpXeFResp0HNlt8NSu13vhC08j
|
|
23
|
+
GUHU9MyIXbFOsnp3K3ADrAVjPWop8EZkmUR3MV/CUm00w2cZHCSGiXl1KMpiVKvk
|
|
24
|
+
Ywr1gd2ZME4QLSo+EXUtLxDUa/W3xnBS8dBOuMMz02FPWYr3PN8CAwEAAaM5MDcw
|
|
25
|
+
CQYDVR0TBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0OBBYEFAFgmv0tYMZnItuPycSM
|
|
26
|
+
F5wykJEVMA0GCSqGSIb3DQEBCwUAA4IBgQBlzRfyAYx/fCFjizS0Npxw4+4T3aYL
|
|
27
|
+
hbXoDqQRWjxuhFZcXUymhz3r8/Ltyri9lSof8grzB+8/+mrMVms7Gwt5qolk6zdn
|
|
28
|
+
FkySGy/jmpN12ldOHFbBEnyVBZNBvOBVb8zkkw8PhiHdBdXOUm4Jy39yJvBLfjcC
|
|
29
|
+
iM1aeWPmgPy1GbvZU+leRGZLt6dRIR9oCDXcWLRjha8xLMoz6Yn9fJBYexBA3iEz
|
|
30
|
+
h5S7pn4AX/JhVRiSyl8pAy4jEKydpyQrliH3gHkpNmUS/XDczP+9xX1bAB4BvqL2
|
|
31
|
+
NCxMcQ+hiJNqCKpPgHxaOOHZfIxV33logIuPEQ8NryHAwZ9ZWnwtYDE8kQGGKskI
|
|
32
|
+
Kkm6QT474hZl7MpwiJjWgW313CR7jUEekQahX1QxCxHPI7LSrKpno0plH3uWIOQp
|
|
33
|
+
KUlkb9uyACBgyRO52ZHiDVI8YvtU5O/j9pSes9/3XgvBeC1onx4qWp+uRX7eVsYS
|
|
34
|
+
GiijocTc3enZVrXERetaXj8/9XWs3fB3HWY=
|
|
35
|
+
-----END CERTIFICATE-----
|
|
10
36
|
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
37
|
dependencies:
|
|
12
|
-
- !ruby/object:Gem::Dependency
|
|
13
|
-
name: base64
|
|
14
|
-
requirement: !ruby/object:Gem::Requirement
|
|
15
|
-
requirements:
|
|
16
|
-
- - ">="
|
|
17
|
-
- !ruby/object:Gem::Version
|
|
18
|
-
version: '0'
|
|
19
|
-
type: :runtime
|
|
20
|
-
prerelease: false
|
|
21
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
-
requirements:
|
|
23
|
-
- - ">="
|
|
24
|
-
- !ruby/object:Gem::Version
|
|
25
|
-
version: '0'
|
|
26
38
|
- !ruby/object:Gem::Dependency
|
|
27
39
|
name: liquid
|
|
28
40
|
requirement: !ruby/object:Gem::Requirement
|
|
29
41
|
requirements:
|
|
30
42
|
- - "~>"
|
|
31
43
|
- !ruby/object:Gem::Version
|
|
32
|
-
version: '5.
|
|
44
|
+
version: '5.11'
|
|
33
45
|
type: :runtime
|
|
34
46
|
prerelease: false
|
|
35
47
|
version_requirements: !ruby/object:Gem::Requirement
|
|
36
48
|
requirements:
|
|
37
49
|
- - "~>"
|
|
38
50
|
- !ruby/object:Gem::Version
|
|
39
|
-
version: '5.
|
|
51
|
+
version: '5.11'
|
|
40
52
|
- !ruby/object:Gem::Dependency
|
|
41
53
|
name: redcarpet
|
|
42
54
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -57,54 +69,44 @@ dependencies:
|
|
|
57
69
|
requirements:
|
|
58
70
|
- - "~>"
|
|
59
71
|
- !ruby/object:Gem::Version
|
|
60
|
-
version: '3.
|
|
72
|
+
version: '3.2'
|
|
61
73
|
type: :runtime
|
|
62
74
|
prerelease: false
|
|
63
75
|
version_requirements: !ruby/object:Gem::Requirement
|
|
64
76
|
requirements:
|
|
65
77
|
- - "~>"
|
|
66
78
|
- !ruby/object:Gem::Version
|
|
67
|
-
version: '3.
|
|
68
|
-
- !ruby/object:Gem::Dependency
|
|
69
|
-
name: securerandom
|
|
70
|
-
requirement: !ruby/object:Gem::Requirement
|
|
71
|
-
requirements:
|
|
72
|
-
- - ">="
|
|
73
|
-
- !ruby/object:Gem::Version
|
|
74
|
-
version: '0.3'
|
|
75
|
-
type: :runtime
|
|
76
|
-
prerelease: false
|
|
77
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
78
|
-
requirements:
|
|
79
|
-
- - ">="
|
|
80
|
-
- !ruby/object:Gem::Version
|
|
81
|
-
version: '0.3'
|
|
79
|
+
version: '3.2'
|
|
82
80
|
- !ruby/object:Gem::Dependency
|
|
83
81
|
name: tzinfo
|
|
84
82
|
requirement: !ruby/object:Gem::Requirement
|
|
85
83
|
requirements:
|
|
86
|
-
- - "
|
|
84
|
+
- - "~>"
|
|
87
85
|
- !ruby/object:Gem::Version
|
|
88
|
-
version: '0'
|
|
86
|
+
version: '2.0'
|
|
89
87
|
type: :runtime
|
|
90
88
|
prerelease: false
|
|
91
89
|
version_requirements: !ruby/object:Gem::Requirement
|
|
92
90
|
requirements:
|
|
93
|
-
- - "
|
|
91
|
+
- - "~>"
|
|
94
92
|
- !ruby/object:Gem::Version
|
|
95
|
-
version: '0'
|
|
93
|
+
version: '2.0'
|
|
96
94
|
email:
|
|
97
|
-
- engineering@
|
|
95
|
+
- engineering@trmnl.com
|
|
98
96
|
executables: []
|
|
99
97
|
extensions: []
|
|
100
|
-
extra_rdoc_files:
|
|
98
|
+
extra_rdoc_files:
|
|
99
|
+
- LICENSE.txt
|
|
100
|
+
- README.md
|
|
101
101
|
files:
|
|
102
|
+
- LICENSE.txt
|
|
103
|
+
- README.md
|
|
102
104
|
- lib/trmnl/liquid.rb
|
|
103
105
|
- lib/trmnl/liquid/fallback.rb
|
|
104
|
-
- lib/trmnl/liquid/file_system.rb
|
|
105
106
|
- lib/trmnl/liquid/filters.rb
|
|
107
|
+
- lib/trmnl/liquid/memory_system.rb
|
|
108
|
+
- lib/trmnl/liquid/rails_helpers.rb
|
|
106
109
|
- lib/trmnl/liquid/template_tag.rb
|
|
107
|
-
- lib/trmnl/liquid/version.rb
|
|
108
110
|
- trmnl-liquid.gemspec
|
|
109
111
|
homepage: https://github.com/usetrmnl/trmnl-liquid
|
|
110
112
|
licenses:
|
|
@@ -123,14 +125,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
123
125
|
requirements:
|
|
124
126
|
- - ">="
|
|
125
127
|
- !ruby/object:Gem::Version
|
|
126
|
-
version:
|
|
128
|
+
version: '4.0'
|
|
127
129
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
128
130
|
requirements:
|
|
129
131
|
- - ">="
|
|
130
132
|
- !ruby/object:Gem::Version
|
|
131
133
|
version: '0'
|
|
132
134
|
requirements: []
|
|
133
|
-
rubygems_version:
|
|
135
|
+
rubygems_version: 4.0.5
|
|
134
136
|
specification_version: 4
|
|
135
137
|
summary: Liquid templating engine for TRMNL plugins
|
|
136
138
|
test_files: []
|
metadata.gz.sig
ADDED
|
Binary file
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
module TRMNL
|
|
2
|
-
module Liquid
|
|
3
|
-
# This in-memory "file system" is the backing storage for custom templates defined {% template [name] %} tags.
|
|
4
|
-
class FileSystem < ::Liquid::BlankFileSystem
|
|
5
|
-
def initialize
|
|
6
|
-
super
|
|
7
|
-
@templates = {}
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
# called by Markup::LiquidTemplateTag to save users' custom shared templates via our custom {% template %} tag
|
|
11
|
-
def register(name, body)
|
|
12
|
-
@templates[name] = body
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
# called by ::Liquid::Template for {% render 'foo' %} when rendering screen markup
|
|
16
|
-
def read_template_file(name)
|
|
17
|
-
@templates[name] || raise(::Liquid::FileSystemError, "Template not found: #{name}")
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
end
|