trmnl_preview 0.20.0 → 0.21.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4db6e3e57f6772dd1af033e4ccb533ee516344b66d859b63185d23129a724ef5
4
- data.tar.gz: 8415b8724cf0535880ab4c4e0a6ca42771363f7adae620fcca0bd290468a0d0c
3
+ metadata.gz: d1b736ce74a0385dda5b989fe604d0256d0b1522b1955855aa0eac945ec3dd0b
4
+ data.tar.gz: f4b4321d72bd9129a025f07d21707f0584e965a5bfe072db3ecc95c2fbf04921
5
5
  SHA512:
6
- metadata.gz: b440d6525409a971f262d09d7914d7be562dfadf617d1463c03b92519e848bd29b20e9e53fb30e7a1cf964919723e7e3e64364b573609ab7fbc2d215acdd97af
7
- data.tar.gz: 96ce3caffe6bd63267aad0f6f9aa53a4471ddd6f308447e31040aed8968e77d3a4d82048ff44c4b80ccfbf4678284099f846c4d68f821effebd8bc53454637e2
6
+ metadata.gz: 3997799add0b42fd60ffd8f6c7d9d3c99696152fe32316e8925cfe1a24eed73f410a7efc86a432a46697d1fbd7fa0fa44c7d8c63727c48c0ff48778035e993f5
7
+ data.tar.gz: 12cf46d3ae00fda1f1e82eb80c5ed2bbe2598208ad84de9ecdc878afcb96b51f27e4ed62630195cdb1a0fc60a8d5b6cbc1d6be2f1ef4833aefdc0c370cd1634d
data/CHANGELOG.md CHANGED
@@ -1,6 +1,16 @@
1
1
 
2
2
  # Changelog
3
3
 
4
+ ## 0.21.0
5
+
6
+ - The `bin/trmnlp` script that `trmnlp init` writes pulls a newer `trmnl/trmnlp` image once a day, so a Docker user stays on the latest release. Before, it ran whatever image was pulled first. The README shows how to install the script as `trmnlp` with Docker alone.
7
+ - The `bin/trmnlp` script that `trmnlp init` writes runs every command in Docker as the gem would. It asked for a terminal it did not have on CI and in scripts (`the input device is not a TTY`), and published port 4567 for every command, so `lint` and `test` failed while `serve` ran and `serve --port` could not be reached. On Linux it runs as you, so snapshots and `_build` are not root's. A plugin's OAuth tokens and saved data are kept between runs, and `CI` and `TRMNL_API_KEY` reach trmnlp. Saved as `trmnlp` on the `PATH`, it no longer starts itself without end. An existing plugin gets the new script from `trmnlp init <its folder>`, answering `y` for `bin/trmnlp` only.
8
+ - The README asks for Ruby >= 4.0 to install the gem, as the gem does. It said 3.4.
9
+ - `trmnlp lint` reports a filter that neither Liquid nor trmnl-liquid defines (`no_unknown_filters`), such as a typo or a LiquidJS filter like `push`. TRMNL outputs the value unfiltered, and `serve` and `build` drew it the same way, so nothing showed the mistake.
10
+ - The Docker image includes geckodriver, so it draws screens on arm64 Linux such as a Raspberry Pi. Selenium downloaded it on every run that draws a screen (`test`, `build`, `serve`), which took about half a second and failed with no network, and on arm64 without x86 emulation it could not download one at all (`Unable to obtain geckodriver`).
11
+ - Every command checks RubyGems for a newer stable release, once a day, and suggests a Gem or Bundler update command on stderr; `trmnlp version` always asks. `--quiet` or `TRMNLP_NO_UPDATE_NOTIFIER=1` skips it, and network failures leave output and exit status unchanged.
12
+ - `have_no_overflow(except: '.forecast')` and `screen.overflowing(except:)` leave out a box that hides content on purpose, and everything inside it.
13
+
4
14
  ## 0.20.0
5
15
 
6
16
  - `trmnlp lint` skips the rules listed under `ignored_lint_rules` in `.trmnlp.yml`, in text and JSON output alike. An unknown rule ID is an error that lists the known ones.
data/README.md CHANGED
@@ -100,6 +100,17 @@ trmnlp push # upload
100
100
 
101
101
  `trmnlp lint` exits non-zero when it finds issues, so you can gate CI on it. Run `trmnlp help` for all flags.
102
102
 
103
+ Every command also checks RubyGems for a newer stable `trmnl_preview` release
104
+ and, when one is available, suggests `gem update trmnl_preview`, or
105
+ `bundle update trmnl_preview` when run through Bundler. An exact Gemfile pin must
106
+ be changed before Bundler can update it. Notices go to stderr, keeping lint JSON
107
+ output and exit status unchanged. The answer is cached for a day, so most runs
108
+ make no request; `trmnlp version` always asks RubyGems. `--quiet` or
109
+ `TRMNLP_NO_UPDATE_NOTIFIER=1` skips the check. Connection and read timeouts are
110
+ two seconds each; current versions and an unavailable registry stay silent. The
111
+ check never installs an update or changes your Gemfile or lockfile. Inside Docker there is no
112
+ check: the `bin/trmnlp` script pulls a newer image once a day instead.
113
+
103
114
  Lint findings include a stable snake_case rule ID, severity and source locations.
104
115
  Locations use project-relative paths and one-based line/column numbers, followed
105
116
  by a source excerpt (up to 240 characters). Aggregate checks show their contributing
@@ -123,6 +134,8 @@ Liquid in declaration values is counted without rendering the plugin, every bran
123
134
  Filters from `custom_filters` in `.trmnlp.yml` exist only in trmnlp. TRMNL does not load them
124
135
  and outputs the value unfiltered, so `no_custom_filters` reports each place the markup uses one.
125
136
  Filters that trmnl-liquid also provides are not reported.
137
+ A filter that neither Liquid nor trmnl-liquid defines, such as a typo or one from another
138
+ Liquid (Jekyll, LiquidJS), is also output unfiltered on TRMNL, so `no_unknown_filters` reports it.
126
139
 
127
140
  To accept a rule's findings, list its rule ID under `ignored_lint_rules` in `.trmnlp.yml`.
128
141
  `trmnlp lint` then skips that check in both formats, so the CLI and CI agree. An unknown
@@ -214,13 +227,13 @@ The `bin/trmnlp` script is provided as a convenience. It will use the local Ruby
214
227
 
215
228
  You can modify the `bin/trmnlp` script to set up environment variables (plugin secrets, etc.) before running the server.
216
229
 
217
- **Gem or Docker?** Install the gem if you already have Ruby >= 3.4 — it has the fastest startup. Use Docker for zero local setup.
230
+ **Gem or Docker?** Install the gem if you already have Ruby >= 4.0 — it has the fastest startup. Use Docker for zero local setup.
218
231
 
219
232
  ### Installing via RubyGems
220
233
 
221
234
  Prerequisites:
222
235
 
223
- - Ruby >= 3.4
236
+ - Ruby >= 4.0
224
237
  - For PNG rendering (optional):
225
238
  - Firefox
226
239
  - ImageMagick
@@ -232,6 +245,20 @@ trmnlp serve
232
245
 
233
246
  ### Installing via Docker
234
247
 
248
+ To type `trmnlp` as with the gem, copy the script from the image onto your `PATH`:
249
+
250
+ ```sh
251
+ mkdir -p ~/.local/bin
252
+ docker run --rm --entrypoint cat trmnl/trmnlp /app/templates/init/bin/trmnlp > ~/.local/bin/trmnlp
253
+ chmod +x ~/.local/bin/trmnlp
254
+ ```
255
+
256
+ It runs each command in the image and pulls a newer image once a day. To stay on one release,
257
+ set `IMAGE` in the script to a tag such as `trmnl/trmnlp:v0.20.0`. `trmnlp init` puts the same
258
+ script in each plugin as `bin/trmnlp`.
259
+
260
+ Or run the image yourself:
261
+
235
262
  ```sh
236
263
  docker run \
237
264
  --pull always \
data/lib/trmnlp/cli.rb CHANGED
@@ -4,6 +4,8 @@ require 'thor'
4
4
 
5
5
  require_relative '../trmnlp'
6
6
  require_relative '../trmnlp/commands'
7
+ require_relative 'paths'
8
+ require_relative 'update_check'
7
9
 
8
10
  module TRMNLP
9
11
  class CLI < Thor
@@ -22,6 +24,23 @@ module TRMNLP
22
24
  def self.in_container? = File.exist?('/.dockerenv') || File.exist?('/run/.containerenv')
23
25
  def self.default_bind = in_container? ? '0.0.0.0' : '127.0.0.1'
24
26
 
27
+ no_commands do
28
+ # Thor routes every command through here, so the update notice covers
29
+ # them all without each command having to remember it. `version` runs
30
+ # its own fresh check after printing, and help has nothing to update.
31
+ def invoke_command(command, *)
32
+ check_for_update unless %w[help version].include?(command.name)
33
+ super
34
+ end
35
+
36
+ def check_for_update(fresh: false)
37
+ # In a container `gem update` does not apply; bin/trmnlp pulls a newer image instead.
38
+ return if options[:quiet] || UpdateCheck.disabled? || self.class.in_container?
39
+
40
+ UpdateCheck.new(Paths.new(options[:dir]).update_check).call(fresh:)
41
+ end
42
+ end
43
+
25
44
  desc 'build', 'Generate static HTML files'
26
45
  method_option :png, type: :boolean, default: false, desc: 'Also render a PNG per view'
27
46
  method_option :width, type: :numeric, desc: 'PNG width in pixels (with --png)'
@@ -96,6 +115,9 @@ module TRMNLP
96
115
  desc 'version', 'Show version'
97
116
  def version
98
117
  puts VERSION
118
+ # Keep the version first when stdout is a pipe and stderr is not.
119
+ $stdout.flush
120
+ check_for_update(fresh: true)
99
121
  end
100
122
  end
101
123
  end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'trmnl/liquid'
4
+
5
+ require_relative '../check'
6
+
7
+ module TRMNLP
8
+ module Lint
9
+ module Checks
10
+ # Reports markup that uses a filter neither Liquid nor trmnl-liquid defines, such
11
+ # as a typo or a filter from another Liquid (Jekyll, LiquidJS). TRMNL does not fail
12
+ # on one: it outputs the value unfiltered. custom_filters are no_custom_filters' to report.
13
+ class NoUnknownFilters < Check
14
+ def issues
15
+ unknown_filter_names.map do |name|
16
+ { message: "Filter '#{name}' is not a Liquid or TRMNL filter. TRMNL outputs the value unfiltered; " \
17
+ 'check the name, or use a built-in filter or the transform instead.' }
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ def unknown_filter_names
24
+ used_filter_names - environment.filter_method_names - source.local_only_filter_names
25
+ end
26
+
27
+ def used_filter_names = source.markup_files.values.flat_map { filter_names(it) }.uniq
28
+
29
+ # Liquid's own parse, so a pipe in a string or a raw block is not taken for a filter.
30
+ def filter_names(markup)
31
+ names = []
32
+ template = ::Liquid::Template.parse(markup, environment:)
33
+ ::Liquid::ParseTreeVisitor.for(template.root)
34
+ .add_callback_for(::Liquid::Variable) { names.concat(it.filters.map(&:first)) }
35
+ .visit
36
+ names
37
+ rescue ::Liquid::SyntaxError
38
+ [] # A template that does not parse fails to render, which says so.
39
+ end
40
+
41
+ # trmnl-liquid's template tag keeps its body as a String, which ParseTreeVisitor cannot walk.
42
+ def environment = @environment ||= TRMNL::Liquid.new { it.register_tag 'template', ::Liquid::Block }
43
+ end
44
+ end
45
+ end
46
+ end
@@ -44,7 +44,7 @@ module TRMNLP
44
44
  when 'layouts_have_content' then empty_view_locations
45
45
  when 'form_fields_valid' then form_field_locations
46
46
  when 'custom_fields_used' then project_field_locations
47
- when 'no_custom_filters' then custom_filter_locations
47
+ when 'no_custom_filters', 'no_unknown_filters' then filter_locations
48
48
  when 'image_links_reachable' then source.locations(Regexp.union(check.unreachable_urls))
49
49
  else []
50
50
  end
@@ -55,7 +55,7 @@ module TRMNLP
55
55
  css_class ? source.locations(Regexp.new(Regexp.escape(css_class))) : []
56
56
  end
57
57
 
58
- def custom_filter_locations
58
+ def filter_locations
59
59
  source.locations(Checks::NoCustomFilters.usage_pattern(finding[:message][/Filter '([^']+)'/, 1]))
60
60
  end
61
61
 
data/lib/trmnlp/lint.rb CHANGED
@@ -19,6 +19,7 @@ require_relative 'lint/checks/image_links_reachable'
19
19
  require_relative 'lint/checks/custom_fields_used'
20
20
  require_relative 'lint/checks/form_fields_valid'
21
21
  require_relative 'lint/checks/no_custom_filters'
22
+ require_relative 'lint/checks/no_unknown_filters'
22
23
 
23
24
  module TRMNLP
24
25
  # Markup best-practice checks behind `trmnlp lint`.
@@ -41,7 +42,8 @@ module TRMNLP
41
42
  Checks::ImageLinksReachable,
42
43
  Checks::CustomFieldsUsed,
43
44
  Checks::FormFieldsValid,
44
- Checks::NoCustomFilters
45
+ Checks::NoCustomFilters,
46
+ Checks::NoUnknownFilters
45
47
  ].freeze
46
48
 
47
49
  def self.rule_id(check_type) = check_type.name.split('::').last.gsub(/([a-z\d])([A-Z])/, '\1_\2').downcase
data/lib/trmnlp/paths.rb CHANGED
@@ -55,6 +55,9 @@ module TRMNLP
55
55
 
56
56
  def transform_output = cache_dir.join('transform_output', "#{project_key}.json")
57
57
 
58
+ # One file for every project: the published gem version is not per project.
59
+ def update_check = cache_dir.join('update_check.json')
60
+
58
61
  def render_template = Pathname.new(__dir__).join('..', '..', 'web', 'views', 'render_html.erb')
59
62
 
60
63
  def src_files = src_dir.glob('*').select(&:file?)
@@ -46,10 +46,10 @@ module TRMNLP
46
46
  end
47
47
  end
48
48
 
49
- RSpec::Matchers.define :have_no_overflow do
50
- match { |screen| screen.overflowing.empty? }
49
+ RSpec::Matchers.define :have_no_overflow do |except: nil|
50
+ match { |screen| screen.overflowing(except:).empty? }
51
51
  failure_message do |screen|
52
- "expected nothing to overflow on #{screen.inspect}, but: #{screen.overflowing.join(', ')}"
52
+ "expected nothing to overflow on #{screen.inspect}, but: #{screen.overflowing(except:).join(', ')}"
53
53
  end
54
54
  end
55
55
 
@@ -15,6 +15,7 @@ module TRMNLP
15
15
 
16
16
  # Every element drawn past the screen's edge, and every box that cuts a child box or a glyph's ink.
17
17
  OVERFLOW_SCRIPT = <<~JS
18
+ const except = arguments[0];
18
19
  const screen = document.documentElement.getBoundingClientRect();
19
20
  const describe = (el) => el.tagName.toLowerCase() + (el.id ? '#' + el.id : '') +
20
21
  (el.classList.length ? '.' + [...el.classList].join('.') : '');
@@ -78,7 +79,7 @@ module TRMNLP
78
79
  };
79
80
  return [...document.querySelectorAll('.view *')].filter((el) => {
80
81
  const box = el.getBoundingClientRect();
81
- if (!drawn(box) || insideTruncation(el)) return false;
82
+ if (!drawn(box) || insideTruncation(el) || (except && el.closest(except))) return false;
82
83
  const outside = box.right > screen.right + 1 || box.bottom > screen.bottom + 1 || box.left < -1 || box.top < -1;
83
84
  const style = getComputedStyle(el);
84
85
  const overflows = el.scrollWidth > el.clientWidth + 1 || el.scrollHeight > el.clientHeight + 1;
@@ -123,7 +124,7 @@ module TRMNLP
123
124
 
124
125
  def evaluate(expression) = @browser.on(self) { it.execute_script("return (#{expression});") }
125
126
 
126
- def overflowing = @browser.on(self) { it.execute_script(OVERFLOW_SCRIPT) }
127
+ def overflowing(except: nil) = @browser.on(self) { it.execute_script(OVERFLOW_SCRIPT, except) }
127
128
 
128
129
  # Script errors, unhandled rejections, console.error lines and files that failed to load.
129
130
  def problems = evaluate('window.__trmnlpProblems || []')
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'faraday'
4
+ require 'json'
5
+ require_relative 'reporter'
6
+ require_relative 'version'
7
+
8
+ module TRMNLP
9
+ # Tells the user when RubyGems has a newer trmnl_preview. The answer is
10
+ # cached for a day so routine commands do not wait on the network; a
11
+ # failed lookup is cached too, so an offline run stalls at most once a day.
12
+ class UpdateCheck
13
+ ENDPOINT = 'https://rubygems.org/api/v1/gems/trmnl_preview.json'
14
+ TIMEOUT = 2
15
+ CACHE_TTL = 24 * 60 * 60
16
+ DISABLE_ENV_KEY = 'TRMNLP_NO_UPDATE_NOTIFIER'
17
+
18
+ def self.disabled? = !ENV[DISABLE_ENV_KEY].to_s.empty?
19
+
20
+ def initialize(cache_path, reporter: Reporter.new(stream: $stderr))
21
+ @cache_path = Pathname.new(cache_path)
22
+ @reporter = reporter
23
+ end
24
+
25
+ # Reports a newer stable release. fresh: asks RubyGems now instead of
26
+ # trusting a cached answer from the last day.
27
+ def call(fresh: false)
28
+ latest = fresh ? refresh : cached
29
+ return unless latest && latest > Gem::Version.new(VERSION)
30
+
31
+ reporter.info("trmnl_preview #{latest} is available (installed: #{VERSION}).")
32
+ reporter.info(update_guidance)
33
+ end
34
+
35
+ private
36
+
37
+ attr_reader :cache_path, :reporter
38
+
39
+ def cached
40
+ cache = read_cache
41
+ return version_from(cache['version']) if cache && Time.now.to_i - cache['checked_at'] < CACHE_TTL
42
+
43
+ refresh
44
+ end
45
+
46
+ def refresh
47
+ latest = fetch_latest
48
+ write_cache(latest)
49
+ latest
50
+ end
51
+
52
+ def read_cache
53
+ data = JSON.parse(cache_path.read)
54
+ data if data.is_a?(Hash) && data['checked_at'].is_a?(Integer)
55
+ rescue SystemCallError, JSON::ParserError
56
+ nil
57
+ end
58
+
59
+ def write_cache(latest)
60
+ cache_path.dirname.mkpath
61
+ cache_path.write(JSON.generate(checked_at: Time.now.to_i, version: latest&.to_s))
62
+ rescue SystemCallError
63
+ nil
64
+ end
65
+
66
+ def fetch_latest
67
+ response = Faraday.get(ENDPOINT) do |request|
68
+ request.options.open_timeout = TIMEOUT
69
+ request.options.timeout = TIMEOUT
70
+ end
71
+ parse_version(response.body) if response.success?
72
+ rescue Faraday::Error, JSON::ParserError, ArgumentError
73
+ nil
74
+ end
75
+
76
+ def parse_version(body)
77
+ data = JSON.parse(body)
78
+ version_from(data['version']) if data.is_a?(Hash)
79
+ end
80
+
81
+ def version_from(value)
82
+ return unless value.is_a?(String) && !value.empty? && Gem::Version.correct?(value)
83
+
84
+ version = Gem::Version.new(value)
85
+ version unless version.prerelease?
86
+ end
87
+
88
+ def update_guidance
89
+ return 'Update with: gem update trmnl_preview' if ENV['BUNDLE_GEMFILE'].to_s.empty?
90
+
91
+ 'Update the trmnl_preview constraint in your Gemfile if needed, then run: bundle update trmnl_preview'
92
+ end
93
+ end
94
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TRMNLP
4
- VERSION = '0.20.0'
4
+ VERSION = '0.21.0'
5
5
  end
@@ -4,10 +4,23 @@
4
4
  # Use this opportunity to set up environment variables, install dependencies, etc.
5
5
  #
6
6
 
7
- if command -v trmnlp &> /dev/null
7
+ # Saved on the PATH as `trmnlp`, this script is what `command -v trmnlp` finds: not a gem.
8
+ GEM="$(command -v trmnlp)"
9
+ if [ -n "$GEM" ] && ! [ "$GEM" -ef "$0" ]
8
10
  then
9
- trmnlp "$@"
10
- exit
11
+ exec "$GEM" "$@"
12
+ fi
13
+
14
+ if ! command -v docker &> /dev/null
15
+ then
16
+ echo "Install the trmnl_preview gem:
17
+
18
+ gem install trmnl_preview
19
+
20
+ Or install Docker:
21
+
22
+ https://docs.docker.com/get-docker/"
23
+ exit 1
11
24
  fi
12
25
 
13
26
  # Determine XDG config directory on host OS
@@ -17,28 +30,64 @@ else
17
30
  CONFIG_DIR="$HOME/.config/trmnlp"
18
31
  fi
19
32
 
20
- if [ ! -d "$CONFIG_DIR" ]; then
21
- mkdir -p "$CONFIG_DIR"
33
+ # What trmnlp caches is kept as well: a plugin's OAuth tokens, its saved data and transform state.
34
+ CACHE_DIR="${XDG_CACHE_HOME:-$HOME/.cache}/trmnl"
35
+
36
+ mkdir -p "$CONFIG_DIR" "$CACHE_DIR"
37
+
38
+ # Add a tag to stay on one release: trmnl/trmnlp:v0.20.0
39
+ IMAGE=trmnl/trmnlp
40
+
41
+ # A newer release is pulled once a day. With no network, the image already here runs.
42
+ PULLED_AT="$CACHE_DIR/image_pulled"
43
+ if [ -z "$(find "$PULLED_AT" -mtime -1 2> /dev/null)" ]; then
44
+ docker pull --quiet "$IMAGE" > /dev/null 2>&1
45
+ touch "$PULLED_AT"
22
46
  fi
23
47
 
24
- if command -v docker &> /dev/null
48
+ # On Linux the container's root is the host's root, and the files trmnlp writes (snapshots, _build,
49
+ # a pulled plugin) would be root's. So trmnlp runs as you, with a home of its own to write in.
50
+ # Docker Desktop and rootless Docker hand the files to you already.
51
+ CONTAINER_HOME=/root
52
+ SECURITY="$(docker info --format '{{.SecurityOptions}}' 2> /dev/null)"
53
+ if [ "$(uname)" = Linux ] && [ "$(id -u)" != 0 ] && [ -n "$SECURITY" ] && [[ "$SECURITY" != *rootless* ]]
25
54
  then
26
- docker run \
27
- -it \
28
- --rm \
29
- --publish 4567:4567 \
30
- --volume "$(pwd):/plugin" \
31
- --volume "$CONFIG_DIR:/root/.config/trmnlp" \
32
- trmnl/trmnlp "$@"
33
- exit
55
+ CONTAINER_HOME=/tmp/home
56
+ # .config and .cache are made for you as well: Docker would make them root's to mount the
57
+ # folders below into them, and Firefox hangs when it cannot write there.
58
+ ARGS=(
59
+ --user "$(id -u):$(id -g)"
60
+ --env HOME=/tmp/home
61
+ --tmpfs "/tmp/home:exec,uid=$(id -u),gid=$(id -g)"
62
+ --tmpfs "/tmp/home/.config:uid=$(id -u),gid=$(id -g)"
63
+ --tmpfs "/tmp/home/.cache:exec,uid=$(id -u),gid=$(id -g)"
64
+ )
34
65
  fi
35
66
 
36
- echo "Install the trmnl_preview gem:
37
-
38
- gem install trmnl_preview
39
-
40
- Or install Docker:
67
+ # A terminal only when there is one: CI and scripts have none.
68
+ if [ -t 0 ] && [ -t 1 ]; then
69
+ ARGS+=(--tty)
70
+ fi
41
71
 
42
- https://docs.docker.com/get-docker/"
72
+ # Only serve listens, so every other command can run next to it.
73
+ if [ "$1" = serve ]; then
74
+ PORT=4567
75
+ for ARG in "$@"; do
76
+ case "$PREVIOUS" in -p | --port) PORT="$ARG" ;; esac
77
+ case "$ARG" in --port=*) PORT="${ARG#--port=}" ;; esac
78
+ PREVIOUS="$ARG"
79
+ done
80
+ ARGS+=(--publish "$PORT:$PORT")
81
+ fi
43
82
 
44
- exit 1
83
+ exec docker run \
84
+ --rm \
85
+ --init \
86
+ --interactive \
87
+ "${ARGS[@]}" \
88
+ --env CI \
89
+ --env TRMNL_API_KEY \
90
+ --volume "$CONFIG_DIR:$CONTAINER_HOME/.config/trmnlp" \
91
+ --volume "$CACHE_DIR:$CONTAINER_HOME/.cache/trmnl" \
92
+ --volume "$(pwd):/plugin" \
93
+ "$IMAGE" "$@"
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.20.0
4
+ version: 0.21.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rockwell Schrock
@@ -433,6 +433,7 @@ files:
433
433
  - lib/trmnlp/lint/checks/no_custom_filters.rb
434
434
  - lib/trmnlp/lint/checks/no_opacity.rb
435
435
  - lib/trmnlp/lint/checks/no_size_classes.rb
436
+ - lib/trmnlp/lint/checks/no_unknown_filters.rb
436
437
  - lib/trmnlp/lint/checks/recipe_overview_length.rb
437
438
  - lib/trmnlp/lint/checks/title_casing.rb
438
439
  - lib/trmnlp/lint/checks/title_length.rb
@@ -483,6 +484,7 @@ files:
483
484
  - lib/trmnlp/transform_client.rb
484
485
  - lib/trmnlp/transform_pipeline.rb
485
486
  - lib/trmnlp/transform_state.rb
487
+ - lib/trmnlp/update_check.rb
486
488
  - lib/trmnlp/user_data_assembler.rb
487
489
  - lib/trmnlp/version.rb
488
490
  - lib/trmnlp/watcher.rb