trmnl_preview 0.7.2 → 0.8.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 +192 -0
- data/LICENSE.txt +21 -0
- data/README.md +319 -0
- data/bin/rake +27 -0
- data/bin/trmnlp +13 -14
- data/db/data/form_fields.yml +24 -0
- data/db/data/framework_versions.yml +72 -0
- data/lib/trmnlp/api_client.rb +99 -0
- data/lib/trmnlp/app.rb +132 -0
- data/lib/trmnlp/browser_pool.rb +82 -0
- data/lib/trmnlp/cli.rb +81 -0
- data/lib/trmnlp/commands/base.rb +63 -0
- data/lib/trmnlp/commands/build.rb +26 -0
- data/lib/trmnlp/commands/clone.rb +35 -0
- data/lib/trmnlp/commands/init.rb +59 -0
- data/lib/trmnlp/commands/lint.rb +42 -0
- data/lib/trmnlp/commands/list.rb +40 -0
- data/lib/trmnlp/commands/login.rb +42 -0
- data/lib/trmnlp/commands/pull.rb +51 -0
- data/lib/trmnlp/commands/push.rb +77 -0
- data/lib/trmnlp/commands/serve.rb +54 -0
- data/lib/trmnlp/commands.rb +3 -0
- data/lib/trmnlp/config/app.rb +50 -0
- data/lib/trmnlp/config/plugin.rb +117 -0
- data/lib/trmnlp/config/project.rb +106 -0
- data/lib/trmnlp/config.rb +17 -0
- data/lib/trmnlp/context.rb +35 -0
- data/lib/trmnlp/errors.rb +15 -0
- data/lib/trmnlp/form_field.rb +42 -0
- data/lib/trmnlp/framework_version.rb +69 -0
- data/lib/trmnlp/image_quantizer.rb +58 -0
- data/lib/trmnlp/lint/check.rb +31 -0
- data/lib/trmnlp/lint/checks/custom_fields_used.rb +32 -0
- data/lib/trmnlp/lint/checks/form_fields_valid.rb +20 -0
- data/lib/trmnlp/lint/checks/highcharts_animations_disabled.rb +23 -0
- data/lib/trmnlp/lint/checks/highcharts_elements_unique.rb +24 -0
- data/lib/trmnlp/lint/checks/image_links_reachable.rb +53 -0
- data/lib/trmnlp/lint/checks/layouts_have_content.rb +24 -0
- data/lib/trmnlp/lint/checks/limited_inline_styles.rb +26 -0
- data/lib/trmnlp/lint/checks/no_async_functions.rb +18 -0
- data/lib/trmnlp/lint/checks/no_opacity.rb +19 -0
- data/lib/trmnlp/lint/checks/no_size_classes.rb +19 -0
- data/lib/trmnlp/lint/checks/title_casing.rb +20 -0
- data/lib/trmnlp/lint/checks/title_length.rb +18 -0
- data/lib/trmnlp/lint/checks/waits_for_dom_load.rb +23 -0
- data/lib/trmnlp/lint/source.rb +42 -0
- data/lib/trmnlp/lint.rb +39 -0
- data/lib/trmnlp/paths.rb +78 -0
- data/lib/trmnlp/poller.rb +105 -0
- data/lib/trmnlp/renderer.rb +87 -0
- data/lib/trmnlp/reporter.rb +28 -0
- data/lib/trmnlp/screen.rb +16 -0
- data/lib/trmnlp/screen_generator.rb +34 -0
- data/lib/trmnlp/screenshot.rb +96 -0
- data/lib/trmnlp/transform_backend/http.rb +107 -0
- data/lib/trmnlp/transform_backend/subprocess.rb +130 -0
- data/lib/trmnlp/transform_backend/wrapper.rb +113 -0
- data/lib/trmnlp/transform_client.rb +47 -0
- data/lib/trmnlp/transform_pipeline.rb +65 -0
- data/lib/trmnlp/user_data_assembler.rb +96 -0
- data/lib/trmnlp/version.rb +5 -0
- data/lib/trmnlp/watcher.rb +60 -0
- data/lib/trmnlp.rb +10 -0
- data/templates/init/.trmnlp.yml +14 -0
- data/templates/init/bin/trmnlp +44 -0
- data/templates/init/src/full.liquid +1 -0
- data/templates/init/src/half_horizontal.liquid +1 -0
- data/templates/init/src/half_vertical.liquid +1 -0
- data/templates/init/src/quadrant.liquid +1 -0
- data/templates/init/src/settings.yml +16 -0
- data/templates/init/src/shared.liquid +1 -0
- data/templates/init/src/transform.py.example +14 -0
- data/trmnl_preview.gemspec +68 -0
- data/web/public/highlight/highlight.min.js +315 -0
- data/web/public/highlight/styles/atom-one-dark.min.css +1 -0
- data/web/public/index.css +119 -0
- data/web/public/index.js +96 -0
- data/web/public/trmnl-picker.js +656 -0
- data/web/views/index.erb +73 -0
- data/web/views/render_html.erb +25 -0
- metadata +324 -15
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bf11a528033d7882be345a627e2a480f1cdf95a5f9cef22d01f51f5b46012635
|
|
4
|
+
data.tar.gz: 973c3dc1b96f1d7a81ffa8e9fc82f403285d9449463d210684732a43028509d8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 39963f376ff877a4170ce57564876e5cb4bd6eacc23de4b1792a6cba6cd01f4252579fe19c8d678f21144f37e9ba050ed03866b38a3f7aaa9a67521aa324fd04
|
|
7
|
+
data.tar.gz: 835b494bb56d29e9e4b607a482ae05466b08aa527ff38c00fae2a98e87524bbcbb6db78c9abd5dc8288c3b36692008107a1c9bbbdd298c36ddf1d435cd0d2e65
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
|
|
2
|
+
# Changelog
|
|
3
|
+
|
|
4
|
+
## 0.8.0
|
|
5
|
+
|
|
6
|
+
### Housekeeping
|
|
7
|
+
|
|
8
|
+
- Upgraded the development, CI, and Docker baseline to Ruby 4.0.4
|
|
9
|
+
- Replaced the faye-websocket live reload with server-sent events, removing the eventmachine dependency
|
|
10
|
+
- Upgraded `filewatcher` to 3.x for Ruby 4.0 support
|
|
11
|
+
- Upgraded `mini_magick` to 5.x (ImageMagick 7 only)
|
|
12
|
+
- Upgraded `rubyzip` to 3.x
|
|
13
|
+
- Upgraded `puma` to 8.x
|
|
14
|
+
- Upgraded `oj` and `selenium-webdriver` to their latest releases
|
|
15
|
+
- Upgraded `trmnl-liquid` to 0.7 and `xdg` to 10
|
|
16
|
+
- Added the `cgi` gem, removed from Ruby's standard library in 4.0
|
|
17
|
+
- Dropped the redundant `pathname` gem dependency; Ruby provides `Pathname` built in
|
|
18
|
+
- Added `.rspec` configuration and a `Rakefile`
|
|
19
|
+
|
|
20
|
+
### Refactor
|
|
21
|
+
|
|
22
|
+
- Refactored screen generation into focused objects: `Screen`, `Screenshot`, `Renderer`, `ImageQuantizer`, `BrowserPool`, `Reporter`, `Watcher`, `Poller`, `UserDataAssembler`
|
|
23
|
+
- Added support for `text/html` and `text/plain` polling responses with JSON body sniffing (#81)
|
|
24
|
+
- Fixed Liquid conditionals (`{% if %}...{% endif %}`) spanning `polling_headers` values (#79)
|
|
25
|
+
- Fixed multi-select custom_fields being coerced into JSON strings — arrays now preserved (#80)
|
|
26
|
+
- Fixed `trmnl.device.{width,height}` in user-data so they reflect the picker's selected model (#94)
|
|
27
|
+
- Fixed `Permission denied` from `trmnlp clone` on Linux when overwriting template files (#83)
|
|
28
|
+
- Fixed deprecated `convert` warning by switching to mini_magick's `Magick` tool (#89)
|
|
29
|
+
|
|
30
|
+
### Serverless Transforms
|
|
31
|
+
|
|
32
|
+
- Added `transform_runtime:` config in `.trmnlp.yml` — serverless transforms are enabled by default and run whenever a `src/transform.*` file is present; set to `disabled` to turn them off
|
|
33
|
+
- Added `serverless_daemon_url:` override for pointing at a remote transform daemon (production-fidelity testing, shared team daemons)
|
|
34
|
+
- Added `serverless_language:` override (`python`, `ruby`, `php`, `node`)
|
|
35
|
+
- Added detection of `src/transform.{py,rb,php,js}` with language inferred from extension
|
|
36
|
+
- Added `TRMNLP::TransformClient` strategy host that selects `TransformBackend::Subprocess` (default) or `TransformBackend::Http` (when `serverless_daemon_url` is set) via `.from_config`
|
|
37
|
+
- Added `TRMNLP::TransformBackend::Subprocess` — local subprocess execution mirroring the hosted serverless wrapper contract verbatim, output flows back via a per-execution tempfile
|
|
38
|
+
- Added `python3`, `nodejs`, and `php-cli` to the main `Dockerfile`'s runtime stage alongside the existing `ruby` so all four supported transform languages work out of the box — no sidecar required
|
|
39
|
+
- Added transform-error surfacing in the preview UI when execution fails
|
|
40
|
+
- Added filewatcher re-poll when transform source changes (hot reload)
|
|
41
|
+
- Added `examples/hn-stories/` — a complete worked example fetching Hacker News top stories and rendering across all four sizes
|
|
42
|
+
|
|
43
|
+
### Framework Picker
|
|
44
|
+
|
|
45
|
+
- Added `framework_version:` plugin setting in `src/settings.yml` (defaults to `latest`, supports pinning to any released version) — round-trips through `trmnlp push`/`pull` alongside the hosted plugin archive format
|
|
46
|
+
- Added `framework_asset_host:` override in `.trmnlp.yml` for offline / mirrored development
|
|
47
|
+
- Added `TRMNLP::FrameworkVersion` mirroring the hosted framework versioning
|
|
48
|
+
- Added `rake framework:sync` to refresh `db/data/framework_versions.yml` from a local design-system checkout
|
|
49
|
+
- Updated `render_html.erb` to derive CSS/JS URLs from the resolved framework version
|
|
50
|
+
|
|
51
|
+
### FormField & Init Template
|
|
52
|
+
|
|
53
|
+
- Added FormField schema vendored from the hosted service (`db/data/form_fields.yml`) covering the full field-type allowlist
|
|
54
|
+
- Refreshed the `trmnlp init` template to scaffold `framework_version` and transform configuration, including a `transform.py.example`
|
|
55
|
+
- Fixed non-portable `/bin/bash` shebang in the generated `bin/trmnlp` (#78)
|
|
56
|
+
|
|
57
|
+
## 0.7.0
|
|
58
|
+
|
|
59
|
+
- Switch from Puppeteer + CDP to Selenium + WebDriver BiDi (@SorceressLyra)
|
|
60
|
+
|
|
61
|
+
## 0.6.1
|
|
62
|
+
|
|
63
|
+
- Update trmnl-liquid to 0.4.0
|
|
64
|
+
|
|
65
|
+
## 0.6.0
|
|
66
|
+
|
|
67
|
+
- Drop trmnl-component in lieu of plain iframe
|
|
68
|
+
- Add [trmnl-picker](https://github.com/usetrmnl/trmnl-picker) to support new TRMNL and BYOD screens
|
|
69
|
+
- Fix mashup layout previews
|
|
70
|
+
|
|
71
|
+
## 0.5.10
|
|
72
|
+
|
|
73
|
+
- Fix interpolation of multi-line polling URLs with custom fields
|
|
74
|
+
|
|
75
|
+
## 0.5.9
|
|
76
|
+
|
|
77
|
+
- Add `pathname` dependency
|
|
78
|
+
|
|
79
|
+
## 0.5.8
|
|
80
|
+
|
|
81
|
+
- Improve Docker commands in `bin/trmnlp` (@jrand0m, @jbarreiros)
|
|
82
|
+
|
|
83
|
+
## 0.5.7
|
|
84
|
+
|
|
85
|
+
- Use the `trmnl-liquid` gem so tags and filters stay up-to-date with the hosted offering
|
|
86
|
+
|
|
87
|
+
## 0.5.6
|
|
88
|
+
|
|
89
|
+
- Fixed bug that left blank plugins on server after upload failed
|
|
90
|
+
- Fixed bug creating upload.zip after previous upload had failed
|
|
91
|
+
- Added support to read API key fromk `TRMNL_API_KEY` environment variable (@andi4000)
|
|
92
|
+
- Fixed `init` command in Docker container (@jbarreiros)
|
|
93
|
+
- Automatically remove ephemeral Docker container after exit (@andi4000)
|
|
94
|
+
|
|
95
|
+
## 0.5.5
|
|
96
|
+
|
|
97
|
+
- Added dark mode (@stephenyeargin)
|
|
98
|
+
- Added override for `polling_url` in project config (@heroheman)
|
|
99
|
+
- Reworked `bin/dev` into more generic `bin/trmnlp`
|
|
100
|
+
- Fixed pull, push, and clone commands on Windows (@eugenio)
|
|
101
|
+
|
|
102
|
+
## 0.5.4
|
|
103
|
+
|
|
104
|
+
- Added `shared.liquid` file to template (@mariovisic)
|
|
105
|
+
- Stringified custom field values to match production (@mariovisic)
|
|
106
|
+
- Optimized image generation (@sd416)
|
|
107
|
+
- Fixed preview from growing when JSON data becomes too wide (@stephenyeargin)
|
|
108
|
+
|
|
109
|
+
## 0.5.3
|
|
110
|
+
|
|
111
|
+
- Added support for [reusable markup](https://docs.trmnl.com/go/reusing-markup) in `shared.liquid`
|
|
112
|
+
- Replaced custom case images with [\<trmnl-frame\> component](https://github.com/usetrmnl/trmnl-component)
|
|
113
|
+
- Updated custom Liquid filters
|
|
114
|
+
- Added API key validation during `trmnlp login`
|
|
115
|
+
|
|
116
|
+
## 0.5.2
|
|
117
|
+
|
|
118
|
+
- Added `time_zone` project config option, which is injected into `trmnl.user` variables
|
|
119
|
+
- Fixed time zone to always be UTC, matching trmnl.com servers (#38)
|
|
120
|
+
|
|
121
|
+
## 0.5.1
|
|
122
|
+
|
|
123
|
+
- Fixed `trmnl init`
|
|
124
|
+
|
|
125
|
+
## 0.5.0
|
|
126
|
+
|
|
127
|
+
- Added `trmlnp init` command
|
|
128
|
+
- Added `trmnlp clone` command
|
|
129
|
+
- Improved `trmnlp push` to create remote plugin on first publish
|
|
130
|
+
- Changed syntax of `trmnlp push` and `trmnlp pull` commands
|
|
131
|
+
- Added `oj` gem for JSON parsing (#32)
|
|
132
|
+
|
|
133
|
+
## 0.4.0
|
|
134
|
+
|
|
135
|
+
### Plugin Migration Strategy
|
|
136
|
+
|
|
137
|
+
The plugin directory structure has changed to better align with the [plugin archive format](https://help.trmnl.com/en/articles/10542599-importing-and-exporting-private-plugins#h_581fb988f0).
|
|
138
|
+
|
|
139
|
+
Here is a migration strategy for existing plugin repositories:
|
|
140
|
+
|
|
141
|
+
1. Create `.trmnlp.yml` and bring over preview settings from `config.toml` - [see README](README.md)
|
|
142
|
+
2. Rename directory `views/` to `src/`
|
|
143
|
+
3. Create `src/settings.yml` and bring over plugin settings from `config.toml` - [see TRMNL docs](https://help.trmnl.com/en/articles/10542599-importing-and-exporting-private-plugins#h_581fb988f0)
|
|
144
|
+
4. Delete `config.toml`
|
|
145
|
+
|
|
146
|
+
### Changes
|
|
147
|
+
|
|
148
|
+
- Change plugin directory structure (see README for details)
|
|
149
|
+
- Add `login`, `push`, and `pull` commands
|
|
150
|
+
- Bring up-to-date with latest private plugin features:
|
|
151
|
+
- Add `static` strategy
|
|
152
|
+
- Add polling features: multiple URLs, new verbs, and request body
|
|
153
|
+
- Add settings `dark_mode`, `no_screen_padding`, `custom_fields`
|
|
154
|
+
- Add interpolation of custom fields in `polling\_\*` options
|
|
155
|
+
- Add `{{ trmnl }}` variables
|
|
156
|
+
- Add `watch` config
|
|
157
|
+
- Add interpolation of environment variables in `.trmnlp.yml` via `{{ env }}`
|
|
158
|
+
- Add auto-reload when `.trmnlp.yml` or `settings.yml` changes
|
|
159
|
+
- Add variable display
|
|
160
|
+
- Fix crash when #poll_data fails (#12)
|
|
161
|
+
- Fix git runtime error in Docker container (#12)
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
## 0.3.2
|
|
166
|
+
|
|
167
|
+
- Add bitmap rendering
|
|
168
|
+
- Add TRMNL's [custom plugin filters](https://help.trmnl.com/en/articles/10347358-custom-plugin-filters)
|
|
169
|
+
- Add support for user-supplied custom filters
|
|
170
|
+
|
|
171
|
+
## 0.3.1
|
|
172
|
+
|
|
173
|
+
- Add live render
|
|
174
|
+
|
|
175
|
+
## 0.3.0
|
|
176
|
+
|
|
177
|
+
- Add poll button
|
|
178
|
+
- Add case image overlays
|
|
179
|
+
- Add `trmnlp build` command
|
|
180
|
+
- Add support for `url` pointing to a local JSON data file
|
|
181
|
+
|
|
182
|
+
## 0.2.0
|
|
183
|
+
|
|
184
|
+
- Add "commands" concept to `trmnlp` executable
|
|
185
|
+
- `trmnlp serve` improvements
|
|
186
|
+
- Add argument for plugin directory
|
|
187
|
+
- Add options `-b` and `-p` for host bind and port, respectively
|
|
188
|
+
- Add Dockerfile
|
|
189
|
+
|
|
190
|
+
## 0.1.2
|
|
191
|
+
|
|
192
|
+
- Initial working release
|
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,319 @@
|
|
|
1
|
+
# trmnlp
|
|
2
|
+
|
|
3
|
+
[](https://github.com/usetrmnl/trmnlp/actions/workflows/ci.yaml)
|
|
4
|
+
[](https://rubygems.org/gems/trmnl_preview)
|
|
5
|
+
|
|
6
|
+
A basic self-hosted web server to ease the development and sharing of [TRMNL](https://trmnl.com/) plugins.
|
|
7
|
+
|
|
8
|
+
[Liquid](https://shopify.github.io/liquid/) templates are rendered leveraging the [TRMNL Design System](https://trmnl.com/framework). They may be generated as HTML (faster, and a good approximation of the final result) or as PNG images (slower, but more accurate).
|
|
9
|
+
|
|
10
|
+
The server watches the filesystem for changes to the Liquid templates, seamlessly updating the preview without the need to refresh.
|
|
11
|
+
|
|
12
|
+

|
|
13
|
+
|
|
14
|
+
## Quick Start
|
|
15
|
+
|
|
16
|
+
```sh
|
|
17
|
+
gem install trmnl_preview # install
|
|
18
|
+
trmnlp init my_plugin # scaffold a project
|
|
19
|
+
cd my_plugin
|
|
20
|
+
trmnlp serve # preview at http://localhost:4567
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
No Ruby on hand? Run it through Docker instead — see [Installing via Docker](#installing-via-docker).
|
|
24
|
+
|
|
25
|
+
## Project Structure
|
|
26
|
+
|
|
27
|
+
This is the structure of a plugin project:
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
.
|
|
31
|
+
├── .trmnlp.yml
|
|
32
|
+
├── bin
|
|
33
|
+
│ └── trmnlp
|
|
34
|
+
└── src
|
|
35
|
+
├── full.liquid
|
|
36
|
+
├── half_horizontal.liquid
|
|
37
|
+
├── half_vertical.liquid
|
|
38
|
+
├── quadrant.liquid
|
|
39
|
+
├── shared.liquid
|
|
40
|
+
└── settings.yml
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
| File | Purpose |
|
|
44
|
+
|---|---|
|
|
45
|
+
| `.trmnlp.yml` | Local dev-server config — not uploaded to TRMNL |
|
|
46
|
+
| `src/full.liquid` | Markup for the full screen |
|
|
47
|
+
| `src/half_horizontal.liquid` | Top or bottom half of a stacked mashup |
|
|
48
|
+
| `src/half_vertical.liquid` | Left or right half of a side-by-side mashup |
|
|
49
|
+
| `src/quadrant.liquid` | One quarter of a 2x2 mashup |
|
|
50
|
+
| `src/shared.liquid` | Reusable markup included by the other templates |
|
|
51
|
+
| `src/settings.yml` | Plugin configuration — uploaded to TRMNL |
|
|
52
|
+
|
|
53
|
+
## Creating a New Plugin
|
|
54
|
+
|
|
55
|
+
You can start building a plugin locally, then `push` it to the TRMNL server for display on your device.
|
|
56
|
+
|
|
57
|
+
```sh
|
|
58
|
+
trmnlp init [my_plugin] # generate
|
|
59
|
+
cd [my_plugin]
|
|
60
|
+
trmnlp serve # develop locally
|
|
61
|
+
trmnlp login # authenticate
|
|
62
|
+
trmnlp push # upload
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Modifying an Existing Plugin
|
|
66
|
+
|
|
67
|
+
If you have built a plugin with the web-based editor, you can `clone` it, work on it locally, and `push` changes back to the server.
|
|
68
|
+
|
|
69
|
+
```sh
|
|
70
|
+
trmnlp login # authenticate
|
|
71
|
+
trmnlp clone [my_plugin] [id] # first download
|
|
72
|
+
cd [my_plugin]
|
|
73
|
+
trmnlp serve # develop locally
|
|
74
|
+
trmnlp push # upload
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Commands
|
|
78
|
+
|
|
79
|
+
| Command | Description |
|
|
80
|
+
|---|---|
|
|
81
|
+
| `trmnlp init NAME` | Start a new plugin project |
|
|
82
|
+
| `trmnlp serve` | Start a local dev server |
|
|
83
|
+
| `trmnlp build` | Generate static HTML files |
|
|
84
|
+
| `trmnlp lint` | Check plugin code against TRMNL best practices |
|
|
85
|
+
| `trmnlp login` | Authenticate with TRMNL server |
|
|
86
|
+
| `trmnlp list` | List private plugins from TRMNL server |
|
|
87
|
+
| `trmnlp clone NAME ID` | Copy a plugin project from TRMNL server |
|
|
88
|
+
| `trmnlp pull` | Download latest plugin settings from TRMNL server |
|
|
89
|
+
| `trmnlp push` | Upload latest plugin settings to TRMNL server |
|
|
90
|
+
| `trmnlp version` | Show version |
|
|
91
|
+
|
|
92
|
+
`trmnlp lint` exits non-zero when it finds issues, so you can gate CI on it. Run `trmnlp help` for all flags.
|
|
93
|
+
|
|
94
|
+
## Authentication
|
|
95
|
+
|
|
96
|
+
The `trmnlp login` command saves your API key to `~/.config/trmnlp/config.yml`.
|
|
97
|
+
|
|
98
|
+
If an environment variable is more convenient (for example in a CI/CD pipeline), you can set `$TRMNL_API_KEY` instead.
|
|
99
|
+
|
|
100
|
+
## Running trmnlp
|
|
101
|
+
|
|
102
|
+
The `bin/trmnlp` script is provided as a convenience. It will use the local Ruby gem if available, falling back to the `trmnl/trmnlp` Docker image.
|
|
103
|
+
|
|
104
|
+
You can modify the `bin/trmnlp` script to set up environment variables (plugin secrets, etc.) before running the server.
|
|
105
|
+
|
|
106
|
+
**Gem or Docker?** Install the gem if you already have Ruby >= 3.4 — it has the fastest startup. Use Docker for zero local setup.
|
|
107
|
+
|
|
108
|
+
### Installing via RubyGems
|
|
109
|
+
|
|
110
|
+
Prerequisites:
|
|
111
|
+
|
|
112
|
+
- Ruby >= 3.4
|
|
113
|
+
- For PNG rendering (optional):
|
|
114
|
+
- Firefox
|
|
115
|
+
- ImageMagick
|
|
116
|
+
|
|
117
|
+
```sh
|
|
118
|
+
gem install trmnl_preview
|
|
119
|
+
trmnlp serve
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Installing via Docker
|
|
123
|
+
|
|
124
|
+
```sh
|
|
125
|
+
docker run \
|
|
126
|
+
--publish 4567:4567 \
|
|
127
|
+
--volume "$(pwd):/plugin" \
|
|
128
|
+
trmnl/trmnlp serve
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Inside a container, `serve` binds to `0.0.0.0` automatically (it detects `/.dockerenv`) so the preview is reachable from your host browser. Outside Docker it binds to `127.0.0.1`.
|
|
132
|
+
|
|
133
|
+
Swap `serve` for any other command (`lint`, `login`, `clone`, etc.) to run it in a one-off container.
|
|
134
|
+
|
|
135
|
+
#### Interactive Mode
|
|
136
|
+
|
|
137
|
+
For running multiple commands (login, clone, serve), you can start an interactive shell:
|
|
138
|
+
|
|
139
|
+
```sh
|
|
140
|
+
docker run -it \
|
|
141
|
+
--publish 4567:4567 \
|
|
142
|
+
--volume "$HOME/.config/trmnlp:/root/.config/trmnlp" \
|
|
143
|
+
--volume "$(pwd):/plugin" \
|
|
144
|
+
--entrypoint /bin/bash \
|
|
145
|
+
trmnl/trmnlp
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Then run commands inside the container:
|
|
149
|
+
|
|
150
|
+
```sh
|
|
151
|
+
trmnlp login
|
|
152
|
+
trmnlp clone my_plugin 12345
|
|
153
|
+
cd my_plugin
|
|
154
|
+
trmnlp serve
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
The config volume (`$HOME/.config/trmnlp`) persists your API key between sessions.
|
|
158
|
+
|
|
159
|
+
#### Docker Compose
|
|
160
|
+
|
|
161
|
+
For a checked-in config — like [`examples/hn-stories/`](examples/hn-stories/) uses — a minimal `docker-compose.yml`:
|
|
162
|
+
|
|
163
|
+
```yaml
|
|
164
|
+
services:
|
|
165
|
+
trmnlp:
|
|
166
|
+
image: trmnl/trmnlp
|
|
167
|
+
command: ["serve"]
|
|
168
|
+
ports:
|
|
169
|
+
- "4567:4567"
|
|
170
|
+
volumes:
|
|
171
|
+
- .:/plugin
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Then `docker compose up`.
|
|
175
|
+
|
|
176
|
+
#### Building Locally
|
|
177
|
+
|
|
178
|
+
To build the Docker image from source:
|
|
179
|
+
|
|
180
|
+
```sh
|
|
181
|
+
git clone https://github.com/usetrmnl/trmnlp.git
|
|
182
|
+
cd trmnlp
|
|
183
|
+
docker build -t trmnlp .
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
## `.trmnlp.yml` Reference - Project Config
|
|
187
|
+
|
|
188
|
+
The `.trmnlp.yml` file lives in the root of the plugin project, and is for configuring the local dev server.
|
|
189
|
+
|
|
190
|
+
System environment variables are made available in the `{{ env }}` Liquid varible in this file only. This can be used to safely
|
|
191
|
+
supply plugin secrets, like API keys.
|
|
192
|
+
|
|
193
|
+
All fields are optional.
|
|
194
|
+
|
|
195
|
+
```yaml
|
|
196
|
+
---
|
|
197
|
+
# auto-reload when files change (`watch: false` to disable)
|
|
198
|
+
watch:
|
|
199
|
+
- src
|
|
200
|
+
- .trmnlp.yml
|
|
201
|
+
|
|
202
|
+
# values of custom fields (defined in src/settings.yml)
|
|
203
|
+
custom_fields:
|
|
204
|
+
station: "{{ env.ICAO }}" # interpolate $IACO environment variable
|
|
205
|
+
|
|
206
|
+
# Time zone IANA identifier to inject into trmnl.user; see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
|
|
207
|
+
time_zone: America/New_York
|
|
208
|
+
|
|
209
|
+
# Serverless transforms run automatically when a src/transform.*
|
|
210
|
+
# file is present. Set to 'disabled' to turn off.
|
|
211
|
+
transform_runtime: enabled
|
|
212
|
+
|
|
213
|
+
# Optional remote transform daemon URL — when set, transforms POST
|
|
214
|
+
# here instead of running locally. Useful for production-fidelity
|
|
215
|
+
# testing against a real microVM daemon.
|
|
216
|
+
# serverless_daemon_url: https://transforms.your-team.example
|
|
217
|
+
|
|
218
|
+
# Optional explicit language for src/transform.* (otherwise inferred from extension)
|
|
219
|
+
# serverless_language: python
|
|
220
|
+
|
|
221
|
+
# override variables
|
|
222
|
+
variables:
|
|
223
|
+
trmnl:
|
|
224
|
+
user:
|
|
225
|
+
name: Peter Quill
|
|
226
|
+
plugin_settings:
|
|
227
|
+
instance_name: Kevin Bacon Facts
|
|
228
|
+
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
## Serverless Transforms
|
|
232
|
+
|
|
233
|
+
`trmnlp` can run a transform script (`python`, `ruby`, `php`, or `node`) against the polled API response before handing data to your Liquid templates — matching the hosted plugin service's behavior.
|
|
234
|
+
|
|
235
|
+
Drop a file at `src/transform.{py,rb,php,js}` and define a `run(input)` function — transforms are enabled by default, so it runs automatically. To turn them off, set `transform_runtime: disabled` in `.trmnlp.yml`.
|
|
236
|
+
|
|
237
|
+
> **Heads up:** because transforms run by default, a plugin you `clone` or `pull` from somewhere else will execute its `src/transform.*` code on your machine the first time you preview it — there is no opt-in prompt. Review a third-party plugin's transform script before serving it, or set `transform_runtime: disabled`.
|
|
238
|
+
|
|
239
|
+
The transform receives the polled response on stdin as JSON; whatever `run(input)` returns becomes the new merge data.
|
|
240
|
+
|
|
241
|
+
Example `src/transform.py`:
|
|
242
|
+
|
|
243
|
+
```python
|
|
244
|
+
def run(input):
|
|
245
|
+
return {"items": [x["title"] for x in input["data"]]}
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
The trmnlp image bundles `python3`, `node`, `php`, and `ruby` — no sidecar daemon required.
|
|
249
|
+
|
|
250
|
+
### Language detection
|
|
251
|
+
|
|
252
|
+
The transform language comes from the **file extension**:
|
|
253
|
+
|
|
254
|
+
| File | Language |
|
|
255
|
+
|-------------------|----------|
|
|
256
|
+
| `src/transform.py` | `python` |
|
|
257
|
+
| `src/transform.rb` | `ruby` |
|
|
258
|
+
| `src/transform.js` | `node` |
|
|
259
|
+
| `src/transform.php` | `php` |
|
|
260
|
+
|
|
261
|
+
`trmnlp push` uploads the file under its own name, and the hosted service records `serverless_language` from the extension automatically — you don't need to set it by hand. `trmnlp pull` / `trmnlp clone` bring the transform file back under the same name.
|
|
262
|
+
|
|
263
|
+
### Pointing at a remote daemon
|
|
264
|
+
|
|
265
|
+
For production-fidelity testing against a real microVM daemon, set `serverless_daemon_url:` in `.trmnlp.yml`:
|
|
266
|
+
|
|
267
|
+
```yaml
|
|
268
|
+
transform_runtime: enabled
|
|
269
|
+
serverless_daemon_url: https://transforms.your-team.example
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
Provide the daemon's bearer token via `$TRMNL_SERVERLESS_DAEMON_API_KEY` (env-first, mirroring how `$TRMNL_API_KEY` works for trmnl.com auth):
|
|
273
|
+
|
|
274
|
+
```sh
|
|
275
|
+
export TRMNL_SERVERLESS_DAEMON_API_KEY=...
|
|
276
|
+
trmnlp serve
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
Or commit a per-project value to `.trmnlp.yml` as `serverless_daemon_api_key:` — though the env var is preferred to keep the secret out of version control.
|
|
280
|
+
|
|
281
|
+
A complete worked example lives at [`examples/hn-stories/`](examples/hn-stories/) — a polling plugin that fetches the Hacker News top-stories list, enriches each story via additional HTTPS calls from inside the transform, and renders the result with TRMNL design-system markup across all four sizes. `cd examples/hn-stories && docker compose up` and you're running it.
|
|
282
|
+
|
|
283
|
+
## `src/settings.yml` Reference (Plugin Config)
|
|
284
|
+
|
|
285
|
+
The `settings.yml` file is part of the plugin definition, and is uploaded and downloaded by `trmnlp push` / `pull`.
|
|
286
|
+
|
|
287
|
+
`framework_version:` pins the [TRMNL Design System](https://trmnl.com/framework) version this plugin renders against — `latest` (the default) tracks the newest release, or set a specific version for reproducibility. It lives here rather than in `.trmnlp.yml` so the value round-trips with the hosted plugin service.
|
|
288
|
+
|
|
289
|
+
See [TRMNL documentation](https://help.trmnl.com/en/articles/10542599-importing-and-exporting-private-plugins#h_581fb988f0) for details on this file's contents.
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
## Development
|
|
293
|
+
|
|
294
|
+
To run trmnlp from a checkout of this repo — handy for trying unreleased changes or contributing:
|
|
295
|
+
|
|
296
|
+
```sh
|
|
297
|
+
git clone https://github.com/usetrmnl/trmnlp.git
|
|
298
|
+
cd trmnlp
|
|
299
|
+
bundle install
|
|
300
|
+
bundle exec bin/trmnlp serve
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
The repo pins its Ruby version in `.ruby-version` — a version manager will pick it up when you `cd` in. This `bin/trmnlp` runs the CLI straight from `lib/`; it's a different script from the gem-or-Docker `bin/trmnlp` that `trmnlp init` scaffolds into a plugin project.
|
|
304
|
+
|
|
305
|
+
## Tests
|
|
306
|
+
|
|
307
|
+
To test, run:
|
|
308
|
+
|
|
309
|
+
```sh
|
|
310
|
+
bin/rake
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
## Contributing
|
|
314
|
+
|
|
315
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/usetrmnl/trmnlp.
|
|
316
|
+
|
|
317
|
+
## License
|
|
318
|
+
|
|
319
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/bin/rake
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
#
|
|
5
|
+
# This file was generated by Bundler.
|
|
6
|
+
#
|
|
7
|
+
# The application 'rake' is installed as part of a gem, and
|
|
8
|
+
# this file is here to facilitate running it.
|
|
9
|
+
#
|
|
10
|
+
|
|
11
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
|
|
12
|
+
|
|
13
|
+
bundle_binstub = File.expand_path('bundle', __dir__)
|
|
14
|
+
|
|
15
|
+
if File.file?(bundle_binstub)
|
|
16
|
+
if File.read(bundle_binstub, 300).include?('This file was generated by Bundler')
|
|
17
|
+
load(bundle_binstub)
|
|
18
|
+
else
|
|
19
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
|
20
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
require 'rubygems'
|
|
25
|
+
require 'bundler/setup'
|
|
26
|
+
|
|
27
|
+
load Gem.bin_path('rake', 'rake')
|
data/bin/trmnlp
CHANGED
|
@@ -1,19 +1,18 @@
|
|
|
1
|
-
|
|
1
|
+
#! /usr/bin/env ruby
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
trmnlp requires Ruby 4.0 or newer.
|
|
4
|
+
require 'thor'
|
|
6
5
|
|
|
7
|
-
|
|
8
|
-
instead of trmnlp, because the current release cannot run on your Ruby.
|
|
6
|
+
require_relative '../lib/trmnlp/cli'
|
|
9
7
|
|
|
10
|
-
|
|
8
|
+
# Force UTC to match trmnl.com server time zone
|
|
9
|
+
ENV['TZ'] = 'UTC'
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
11
|
+
begin
|
|
12
|
+
TRMNLP::CLI.start
|
|
13
|
+
rescue TRMNLP::Error => e
|
|
14
|
+
puts "Error: #{e.message}"
|
|
15
|
+
exit 1
|
|
16
|
+
rescue Interrupt
|
|
17
|
+
exit 1
|
|
18
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Form-field schema vendored from the TRMNL hosted service.
|
|
2
|
+
#
|
|
3
|
+
# Unlike framework_versions.yml there is no upstream YAML to sync from —
|
|
4
|
+
# the canonical schema lives in the hosted service's Ruby code. Refresh
|
|
5
|
+
# this file by hand when that schema changes.
|
|
6
|
+
#
|
|
7
|
+
# author_bio is included although the hosted service validates it on a
|
|
8
|
+
# separate branch (so it is absent from the hosted FIELDS allowlist) —
|
|
9
|
+
# it is still a real field type a plugin may declare.
|
|
10
|
+
required_keys:
|
|
11
|
+
- keyname
|
|
12
|
+
- field_type
|
|
13
|
+
- name
|
|
14
|
+
field_types:
|
|
15
|
+
- text
|
|
16
|
+
- string
|
|
17
|
+
- number
|
|
18
|
+
- password
|
|
19
|
+
- boolean
|
|
20
|
+
- xhrString
|
|
21
|
+
- xhrSelect
|
|
22
|
+
- xhrFunction
|
|
23
|
+
- select
|
|
24
|
+
- author_bio
|