trmnl_preview 0.30.3 → 0.31.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 +10 -0
- data/lib/trmnlp/lint/checks/no_negative_spacing.rb +34 -0
- data/lib/trmnlp/lint/diagnostic.rb +2 -1
- data/lib/trmnlp/lint.rb +2 -0
- data/lib/trmnlp/screenshot.rb +5 -1
- data/lib/trmnlp/testing/publishable_recipe.rb +18 -14
- data/lib/trmnlp/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 549b443e84d37972c94d74e4db9559deb402ce49f526e52ad1625ba704db50d5
|
|
4
|
+
data.tar.gz: c0588a1cd534aa350c525efd02410635cd095ccd17974eb6180812e4ae5ca25f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d66bb390b64ab86df09562ab6a789d58973b1510cc0adbfe72dd6a853e7382ea869ee45d8a96b11004148fc2f392047f4b0bc649b0b772bfc258647938f157cf
|
|
7
|
+
data.tar.gz: d805eb40ec0b503e85b724f0ee6ce4a267ac4aa396882144e123221318f585920be6cd09b858720428702152846954cda8ccca5413bbf2da95b438c7b1f9c802
|
data/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
|
|
2
2
|
# Changelog
|
|
3
3
|
|
|
4
|
+
## 0.31.0
|
|
5
|
+
|
|
6
|
+
- `trmnlp test`'s publishable recipe draws the full view with each boolean field on and off, as `"true"` and `"false"`, the strings TRMNL saves. Before, only select fields were drawn with each option, so a recipe that breaks or goes blank with a switch off passed.
|
|
7
|
+
- `option_screens:` draws those options on the screens you name, such as `[{ device: 'og_png' }, { device: 'v2' }]` to try each one on the TRMNL X too. It defaults to the first screen, as before.
|
|
8
|
+
- `trmnlp serve`'s HTML preview draws a device TRMNL scales at its CSS size again, so a TRMNL X fits its 1040 by 780 frame. Since 0.16.0 it drew 1872 by 1404 and ran past the frame. PNG renders and `trmnlp test` are unchanged.
|
|
9
|
+
|
|
10
|
+
## 0.30.4
|
|
11
|
+
|
|
12
|
+
- `trmnlp lint` reports a margin, padding, gap or position class with a leading minus (`no_negative_spacing`), such as `-mt--2` or `lg:-top--1`. Tailwind writes negative values this way, but no Framework release defines a class that starts with a minus, so TRMNL ignores it and says nothing: an icon nudged up with `-mt--1` stays where it was.
|
|
13
|
+
|
|
4
14
|
## 0.30.3
|
|
5
15
|
|
|
6
16
|
- `trmnlp test` serves the Framework's stylesheets, scripts and fonts from a cache in `~/.cache/trmnl/assets`, downloaded from trmnl.com once and kept as long as trmnl.com says. A run no longer fails when trmnl.com is slow or down, as long as the files were fetched before; when a file is due for a refresh and trmnl.com cannot be reached, the copy on disk is used.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../check'
|
|
4
|
+
|
|
5
|
+
module TRMNLP
|
|
6
|
+
module Lint
|
|
7
|
+
module Checks
|
|
8
|
+
# Reports margin, padding, gap and position classes written with a leading
|
|
9
|
+
# minus, such as `-mt--2` or `lg:-top--1`. Tailwind spells negative values
|
|
10
|
+
# this way, but no Framework release, from 1.0.0 to 3.4.2, defines a class
|
|
11
|
+
# that starts with a minus, so the class does nothing and nothing says so:
|
|
12
|
+
# an icon nudged up with `-mt--1` stays where it was.
|
|
13
|
+
class NoNegativeSpacing < Check
|
|
14
|
+
LEARN_MORE = 'https://trmnl.com/framework/docs/spacing'
|
|
15
|
+
|
|
16
|
+
PATTERN = /
|
|
17
|
+
(?<![\w:-])
|
|
18
|
+
(?<prefix>(?:[a-z0-9]+:)*)
|
|
19
|
+
-(?<family>[mp][trblxy]?|gap|top|right|bottom|left|inset)
|
|
20
|
+
--(?<value>[\w.]+)
|
|
21
|
+
(?![\w-])
|
|
22
|
+
/x
|
|
23
|
+
|
|
24
|
+
def issues
|
|
25
|
+
source.all_markup.scan(PATTERN).uniq.map do |prefix, family, value|
|
|
26
|
+
{ message: "'#{prefix}-#{family}--#{value}' has no effect: " \
|
|
27
|
+
"the Framework has no negative '#{family}--' classes.",
|
|
28
|
+
learn_more: LEARN_MORE }
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -43,7 +43,8 @@ module TRMNLP
|
|
|
43
43
|
return source.locations(MARKUP_PATTERNS[rule_id]) if MARKUP_PATTERNS.key?(rule_id)
|
|
44
44
|
|
|
45
45
|
case rule_id
|
|
46
|
-
when 'arbitrary_values_in_range', 'framework_classes_exist', 'framework_prefixes_exist'
|
|
46
|
+
when 'arbitrary_values_in_range', 'no_negative_spacing', 'framework_classes_exist', 'framework_prefixes_exist'
|
|
47
|
+
class_locations
|
|
47
48
|
when 'layouts_have_content' then empty_view_locations
|
|
48
49
|
when 'form_fields_valid' then form_field_locations
|
|
49
50
|
when 'custom_field_links_embedded' then custom_field_description_locations
|
data/lib/trmnlp/lint.rb
CHANGED
|
@@ -13,6 +13,7 @@ require_relative 'lint/checks/limited_inline_styles'
|
|
|
13
13
|
require_relative 'lint/checks/no_style_restyling_framework'
|
|
14
14
|
require_relative 'lint/checks/no_size_classes'
|
|
15
15
|
require_relative 'lint/checks/arbitrary_values_in_range'
|
|
16
|
+
require_relative 'lint/checks/no_negative_spacing'
|
|
16
17
|
require_relative 'lint/checks/no_opacity'
|
|
17
18
|
require_relative 'lint/checks/gray_text_has_one_bit_class'
|
|
18
19
|
require_relative 'lint/checks/highcharts_animations_disabled'
|
|
@@ -52,6 +53,7 @@ module TRMNLP
|
|
|
52
53
|
Checks::NoStyleRestylingFramework,
|
|
53
54
|
Checks::NoSizeClasses,
|
|
54
55
|
Checks::ArbitraryValuesInRange,
|
|
56
|
+
Checks::NoNegativeSpacing,
|
|
55
57
|
Checks::NoOpacity,
|
|
56
58
|
Checks::GrayTextHasOneBitClass,
|
|
57
59
|
Checks::HighchartsAnimationsDisabled,
|
data/lib/trmnlp/screenshot.rb
CHANGED
|
@@ -69,9 +69,13 @@ module TRMNLP
|
|
|
69
69
|
})();
|
|
70
70
|
JS
|
|
71
71
|
|
|
72
|
+
# The preview frame has the device's CSS size, so the screen stays unscaled there.
|
|
73
|
+
LIVE_PREVIEW_SIZE_STYLE = '<style>.trmnl .screen { --pixel-ratio: 1 !important; }</style>'
|
|
74
|
+
|
|
72
75
|
def self.live_preview(html)
|
|
73
76
|
timeout = html.match?(MAPS_DOCUMENT_PATTERN) ? READINESS_TIMEOUT_WITH_MAPS_SECONDS : READINESS_TIMEOUT_SECONDS
|
|
74
|
-
|
|
77
|
+
script = "<script>#{format(SETTLE_LIVE_PREVIEW, timeout)}</script>"
|
|
78
|
+
html.sub('</head>', "#{LIVE_PREVIEW_SIZE_STYLE}#{LAYOUT_PASS_STYLE}#{script}</head>")
|
|
75
79
|
end
|
|
76
80
|
|
|
77
81
|
def initialize(pool:, viewport_timeout: 5, fonts_timeout: FONTS_TIMEOUT_SECONDS)
|
|
@@ -25,21 +25,29 @@ module TRMNLP
|
|
|
25
25
|
# Share of an image's ink its dark mode render must keep: lost icons kept 0%, the lowest one shown 17% (10-14).
|
|
26
26
|
DARK_MODE_MIN_IMAGE_INK_KEPT = 0.05
|
|
27
27
|
|
|
28
|
-
# Each select field's keyname and the values
|
|
29
|
-
def self.
|
|
28
|
+
# Each select and boolean field's keyname and the values it can save, from the plugin's settings.yml.
|
|
29
|
+
def self.option_field_values
|
|
30
30
|
path = File.join(plugin_dir, 'src', 'settings.yml')
|
|
31
31
|
fields = File.exist?(path) ? Array(YAML.safe_load_file(path, aliases: true)&.dig('custom_fields')) : []
|
|
32
|
-
fields.select { it['field_type']
|
|
33
|
-
|
|
32
|
+
fields.select { %w[select boolean].include?(it['field_type']) }.to_h do |field|
|
|
33
|
+
# TRMNL saves a boolean field as the string "true" or "false".
|
|
34
|
+
values = if field['field_type'] == 'boolean' then %w[true false]
|
|
35
|
+
else SelectFieldChoices.new(field).pairs.map { it.last.to_s }
|
|
36
|
+
end
|
|
34
37
|
[field['keyname'], values.size > PUBLISHABLE_RECIPE_MAX_OPTIONS ? values.values_at(0, -1) : values]
|
|
35
38
|
end
|
|
36
39
|
end
|
|
40
|
+
|
|
41
|
+
def self.screen_name(screen)
|
|
42
|
+
device = screen[:device].is_a?(Hash) ? screen[:device][:model] : screen[:device]
|
|
43
|
+
[device, screen[:orientation], screen[:palette], ('dark mode' if screen[:dark_mode])].compact.join(' ')
|
|
44
|
+
end
|
|
37
45
|
end
|
|
38
46
|
end
|
|
39
47
|
|
|
40
48
|
# rubocop:disable-next Metrics/BlockLength -- one shared group, one check per example
|
|
41
49
|
RSpec.shared_examples 'a publishable recipe' do |screens: TRMNLP::Testing::PUBLISHABLE_RECIPE_SCREENS,
|
|
42
|
-
dark_mode_screen: { device: 'v2' }|
|
|
50
|
+
dark_mode_screen: { device: 'v2' }, option_screens: screens.first(1)|
|
|
43
51
|
let(:recipe_inputs) do
|
|
44
52
|
{ mocks: respond_to?(:mocks) ? mocks : {}, custom_fields: respond_to?(:custom_fields) ? custom_fields : {},
|
|
45
53
|
variables: respond_to?(:variables) ? variables : {}, now: respond_to?(:now) ? now : nil,
|
|
@@ -52,11 +60,7 @@ RSpec.shared_examples 'a publishable recipe' do |screens: TRMNLP::Testing::PUBLI
|
|
|
52
60
|
end
|
|
53
61
|
|
|
54
62
|
TRMNLP::Testing::PUBLISHABLE_RECIPE_VIEWS.product(screens).each do |view, screen|
|
|
55
|
-
|
|
56
|
-
dark_mode = 'dark mode' if screen[:dark_mode]
|
|
57
|
-
screen_name = [device, screen[:orientation], screen[:palette], dark_mode].compact.join(' ')
|
|
58
|
-
|
|
59
|
-
it "draws the #{view} view on #{screen_name} without page errors" do
|
|
63
|
+
it "draws the #{view} view on #{TRMNLP::Testing.screen_name(screen)} without page errors" do
|
|
60
64
|
expect(trmnl.render(view:, **screen, **recipe_inputs)).to draw_cleanly
|
|
61
65
|
end
|
|
62
66
|
end
|
|
@@ -76,11 +80,11 @@ RSpec.shared_examples 'a publishable recipe' do |screens: TRMNLP::Testing::PUBLI
|
|
|
76
80
|
end
|
|
77
81
|
end
|
|
78
82
|
|
|
79
|
-
TRMNLP::Testing.
|
|
80
|
-
values.each do |value|
|
|
81
|
-
it "draws the full view with #{keyname} set to #{value}" do
|
|
83
|
+
TRMNLP::Testing.option_field_values.each do |keyname, values|
|
|
84
|
+
option_screens.product(values).each do |screen, value|
|
|
85
|
+
it "draws the full view on #{TRMNLP::Testing.screen_name(screen)} with #{keyname} set to #{value}" do
|
|
82
86
|
custom_fields = recipe_inputs[:custom_fields].merge(keyname => value)
|
|
83
|
-
expect(trmnl.render(**
|
|
87
|
+
expect(trmnl.render(**screen, **recipe_inputs, custom_fields:)).to draw_cleanly
|
|
84
88
|
end
|
|
85
89
|
end
|
|
86
90
|
end
|
data/lib/trmnlp/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: trmnl_preview
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.31.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Rockwell Schrock
|
|
@@ -441,6 +441,7 @@ files:
|
|
|
441
441
|
- lib/trmnlp/lint/checks/no_async_functions.rb
|
|
442
442
|
- lib/trmnlp/lint/checks/no_custom_filters.rb
|
|
443
443
|
- lib/trmnlp/lint/checks/no_external_qr_codes.rb
|
|
444
|
+
- lib/trmnlp/lint/checks/no_negative_spacing.rb
|
|
444
445
|
- lib/trmnlp/lint/checks/no_nested_layouts.rb
|
|
445
446
|
- lib/trmnlp/lint/checks/no_opacity.rb
|
|
446
447
|
- lib/trmnlp/lint/checks/no_refresh_rate_field.rb
|