trmnl_preview 0.19.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.
@@ -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" "$@"
@@ -10,7 +10,7 @@ RSpec.describe 'My Plugin' do
10
10
  # The values of the custom fields in src/settings.yml to test with.
11
11
  let(:custom_fields) { {} }
12
12
 
13
- # Every view on TRMNL's devices, a failing API and every select option, checked for overflow and errors.
13
+ # Every view on TRMNL's devices, a failing API and every select option, checked for page errors and leaked values.
14
14
  it_behaves_like 'a publishable recipe'
15
15
 
16
16
  # A picture of the full view, compared pixel for pixel on every run. Record it once with
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.19.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
@@ -450,7 +451,7 @@ files:
450
451
  - lib/trmnlp/outbound_request.rb
451
452
  - lib/trmnlp/paths.rb
452
453
  - lib/trmnlp/poller.rb
453
- - lib/trmnlp/qr_code_intrinsic_size.rb
454
+ - lib/trmnlp/qr_code.rb
454
455
  - lib/trmnlp/rails_helpers.rb
455
456
  - lib/trmnlp/renderer.rb
456
457
  - lib/trmnlp/reporter.rb
@@ -462,13 +463,14 @@ files:
462
463
  - lib/trmnlp/testing/certificate_authority.rb
463
464
  - lib/trmnlp/testing/device_models.rb
464
465
  - lib/trmnlp/testing/frozen_clock.rb
465
- - lib/trmnlp/testing/inline_stylesheets.rb
466
466
  - lib/trmnlp/testing/memory_sampler.rb
467
467
  - lib/trmnlp/testing/mock_proxy.rb
468
468
  - lib/trmnlp/testing/mock_table.rb
469
469
  - lib/trmnlp/testing/node_version.rb
470
+ - lib/trmnlp/testing/page_server.rb
470
471
  - lib/trmnlp/testing/plugin.rb
471
472
  - lib/trmnlp/testing/publishable_recipe.rb
473
+ - lib/trmnlp/testing/qr_scanner.rb
472
474
  - lib/trmnlp/testing/report.html.erb
473
475
  - lib/trmnlp/testing/report.rb
474
476
  - lib/trmnlp/testing/rspec.rb
@@ -482,6 +484,7 @@ files:
482
484
  - lib/trmnlp/transform_client.rb
483
485
  - lib/trmnlp/transform_pipeline.rb
484
486
  - lib/trmnlp/transform_state.rb
487
+ - lib/trmnlp/update_check.rb
485
488
  - lib/trmnlp/user_data_assembler.rb
486
489
  - lib/trmnlp/version.rb
487
490
  - lib/trmnlp/watcher.rb
@@ -1,22 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'trmnl/liquid'
4
-
5
- module TRMNLP
6
- # Mirrors core's config/initializers/trmnl_liquid_qr_code_intrinsic_size.rb: a view box alone
7
- # gives the code no size of its own, so it renders at zero width in a shrink-to-fit container.
8
- module QrCodeIntrinsicSize
9
- def qr_code(data, size = 11, level = '', view = 'responsive')
10
- svg = super
11
- root_element = svg[/<svg[^>]*>/].to_s
12
- return svg if root_element.include?('width=')
13
-
14
- side_length = root_element[/viewBox="0 0 (\d+)/, 1]
15
- return svg unless side_length
16
-
17
- svg.sub('<svg ', %(<svg width="#{side_length}" height="#{side_length}" style="max-width:100%;height:auto" ))
18
- end
19
- end
20
- end
21
-
22
- TRMNL::Liquid::Filters.prepend(TRMNLP::QrCodeIntrinsicSize)
@@ -1,44 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'faraday'
4
- require 'uri'
5
-
6
- module TRMNLP
7
- module Testing
8
- # Puts a page's linked stylesheets in the page itself. A page written with document.write, as TRMNL and
9
- # trmnlp write theirs, runs its scripts without waiting for linked stylesheets, so a script that
10
- # measures text (a layout solver, say) raced them and drew a different board from run to run.
11
- module InlineStylesheets
12
- LINK = /<link\b[^>]*\brel=["']stylesheet["'][^>]*>/i
13
- SCRIPT = %r{<script\b.*?</script>}im
14
- HREF = /\bhref=["'](https?:[^"']+)["']/i
15
- CSS_URL = /url\(\s*(['"]?)(?!data:|https?:|#)([^'")]+)\1\s*\)/i
16
-
17
- module_function
18
-
19
- def call(html)
20
- html.gsub(Regexp.union(SCRIPT, LINK)) do |tag|
21
- next tag if tag.match?(/\A<script/i)
22
-
23
- url = tag[HREF, 1]
24
- css = url && stylesheet(url)
25
- css ? "<style data-href=\"#{url}\">#{css}</style>" : tag
26
- end
27
- end
28
-
29
- # nil when the stylesheet cannot be fetched: the page keeps its link.
30
- def stylesheet(url)
31
- cache.fetch(url) do
32
- response = Faraday.get(url)
33
- cache[url] = response.success? ? absolute_urls(response.body, url) : nil
34
- end
35
- rescue Faraday::Error
36
- nil
37
- end
38
-
39
- def absolute_urls(css, base) = css.gsub(CSS_URL) { "url(\"#{URI.join(base, Regexp.last_match(2))}\")" }
40
-
41
- def cache = @cache ||= {}
42
- end
43
- end
44
- end