trmnl_preview 0.8.1 → 0.8.3
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 +12 -0
- data/README.md +72 -1
- data/lib/trmnlp/cli.rb +3 -1
- data/lib/trmnlp/commands/clone.rb +2 -2
- data/lib/trmnlp/commands/init.rb +13 -2
- data/lib/trmnlp/framework_version.rb +6 -8
- data/lib/trmnlp/lint/checks/image_links_reachable.rb +2 -2
- data/lib/trmnlp/lint/checks/waits_for_dom_load.rb +2 -1
- data/lib/trmnlp/renderer.rb +1 -1
- data/lib/trmnlp/transform_backend/http.rb +1 -3
- data/lib/trmnlp/transform_backend/wrapper.rb +4 -2
- data/lib/trmnlp/user_data_assembler.rb +3 -3
- data/lib/trmnlp/version.rb +1 -1
- data/templates/init/.github/workflows/trmnl.yml +30 -0
- data/templates/init/.gitignore +2 -0
- data/templates/init/src/full.liquid +7 -1
- data/templates/init/src/half_horizontal.liquid +7 -1
- data/templates/init/src/half_vertical.liquid +7 -1
- data/templates/init/src/quadrant.liquid +7 -1
- data/trmnl_preview.gemspec +5 -2
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c021076f55f8b5d150e65e2202c5bc978e8709684ee4d9bf27c0b7ec8e0b59b8
|
|
4
|
+
data.tar.gz: daa5e5734d9b1e3d755b789b0081916e53ce6c0a3cdd6d75e5276335ad2dae83
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d422c11366ba16381be6765dfb36a25e2a662db4e9da3f3b08b780bbabbd94338d65f0f75bf6cbb82a0aa51fee8660886e5cd14203ccfbd2145539a617823559
|
|
7
|
+
data.tar.gz: 87b5bb57b023748ecc9412e13059801a755e6d0d03c82f27aaacc2077c119ed4386e28fba8a3a4f62ee47b783d4c92e49905d1a47fb29e2f8a93da7caddc563d
|
data/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,18 @@
|
|
|
1
1
|
|
|
2
2
|
# Changelog
|
|
3
3
|
|
|
4
|
+
## 0.8.3
|
|
5
|
+
|
|
6
|
+
- `trmnlp init` and `trmnlp clone` now scaffold a `.github/workflows/trmnl.yml` CI workflow and a `.gitignore`, and run `git init -b main`, so a cloned plugin is ready to push to GitHub and deploy on every commit to `main`
|
|
7
|
+
- Added `--skip-git` to `trmnlp init` and `trmnlp clone` for projects that manage Git themselves
|
|
8
|
+
- The Docker image now ships `git` so the `docker run trmnl/trmnlp clone` flow leaves a ready-to-push project on the host
|
|
9
|
+
- View templates now ship canonical `layout` + `title_bar` markup that passes `trmnlp lint`
|
|
10
|
+
|
|
11
|
+
## 0.8.2
|
|
12
|
+
|
|
13
|
+
- Fixed `framework_version: latest` rendering against the auto-upgrading `/latest/` asset path instead of the current concrete release, matching the hosted service (#99)
|
|
14
|
+
- Cleanup and minor improvements
|
|
15
|
+
|
|
4
16
|
## 0.8.1
|
|
5
17
|
|
|
6
18
|
### Added
|
data/README.md
CHANGED
|
@@ -28,6 +28,10 @@ This is the structure of a plugin project:
|
|
|
28
28
|
|
|
29
29
|
```
|
|
30
30
|
.
|
|
31
|
+
├── .github
|
|
32
|
+
│ └── workflows
|
|
33
|
+
│ └── trmnl.yml
|
|
34
|
+
├── .gitignore
|
|
31
35
|
├── .trmnlp.yml
|
|
32
36
|
├── bin
|
|
33
37
|
│ └── trmnlp
|
|
@@ -42,6 +46,8 @@ This is the structure of a plugin project:
|
|
|
42
46
|
|
|
43
47
|
| File | Purpose |
|
|
44
48
|
|---|---|
|
|
49
|
+
| `.github/workflows/trmnl.yml` | GitHub Actions workflow — lints every PR, deploys to TRMNL on `main` |
|
|
50
|
+
| `.gitignore` | Keeps `trmnlp build` output out of version control |
|
|
45
51
|
| `.trmnlp.yml` | Local dev-server config — not uploaded to TRMNL |
|
|
46
52
|
| `src/full.liquid` | Markup for the full screen |
|
|
47
53
|
| `src/half_horizontal.liquid` | Top or bottom half of a stacked mashup |
|
|
@@ -111,7 +117,7 @@ trmnlp build --png --color-depth 2
|
|
|
111
117
|
| `--png` | Render a PNG per view alongside the HTML |
|
|
112
118
|
| `--width` | PNG width in pixels (default 800) |
|
|
113
119
|
| `--height` | PNG height in pixels (default 480) |
|
|
114
|
-
| `--color-depth` | PNG bit depth — 1
|
|
120
|
+
| `--color-depth` | PNG bit depth — 1-8 — overriding the markup |
|
|
115
121
|
|
|
116
122
|
`--width`, `--height`, and `--color-depth` apply only with `--png`. PNG rendering needs Firefox and ImageMagick installed; plain `trmnlp build` needs neither.
|
|
117
123
|
|
|
@@ -121,6 +127,56 @@ The `trmnlp login` command saves your API key to `~/.config/trmnlp/config.yml`.
|
|
|
121
127
|
|
|
122
128
|
If an environment variable is more convenient (for example in a CI/CD pipeline), you can set `$TRMNL_API_KEY` instead.
|
|
123
129
|
|
|
130
|
+
## Continuous Integration
|
|
131
|
+
|
|
132
|
+
`trmnlp init` and `trmnlp clone` scaffold a `.github/workflows/trmnl.yml`
|
|
133
|
+
workflow and initialize a Git repository, so a fresh project is ready to push
|
|
134
|
+
to GitHub. The workflow runs in GitHub Actions without `trmnlp login` — set the
|
|
135
|
+
`TRMNL_API_KEY` environment variable and it's used in place of the saved
|
|
136
|
+
config. Add it as a repository secret to activate the workflow; it looks like
|
|
137
|
+
this:
|
|
138
|
+
|
|
139
|
+
```yaml
|
|
140
|
+
name: TRMNL
|
|
141
|
+
on:
|
|
142
|
+
pull_request:
|
|
143
|
+
push:
|
|
144
|
+
branches: [main]
|
|
145
|
+
|
|
146
|
+
jobs:
|
|
147
|
+
lint:
|
|
148
|
+
runs-on: ubuntu-latest
|
|
149
|
+
steps:
|
|
150
|
+
- uses: actions/checkout@v6
|
|
151
|
+
- uses: ruby/setup-ruby@v1
|
|
152
|
+
with:
|
|
153
|
+
ruby-version: "4.0"
|
|
154
|
+
- run: gem install trmnl_preview
|
|
155
|
+
- run: trmnlp lint
|
|
156
|
+
|
|
157
|
+
push:
|
|
158
|
+
needs: lint
|
|
159
|
+
if: github.ref == 'refs/heads/main'
|
|
160
|
+
runs-on: ubuntu-latest
|
|
161
|
+
steps:
|
|
162
|
+
- uses: actions/checkout@v6
|
|
163
|
+
- uses: ruby/setup-ruby@v1
|
|
164
|
+
with:
|
|
165
|
+
ruby-version: "4.0"
|
|
166
|
+
- run: gem install trmnl_preview
|
|
167
|
+
- run: trmnlp push --force
|
|
168
|
+
env:
|
|
169
|
+
TRMNL_API_KEY: ${{ secrets.TRMNL_API_KEY }}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
The `lint` job gates every pull request — `trmnlp lint` exits non-zero on
|
|
173
|
+
issues, so a failing check blocks the merge. The `push` job uploads to TRMNL
|
|
174
|
+
only on `main`.
|
|
175
|
+
|
|
176
|
+
> **Make sure `src/settings.yml` has an `id`.** `trmnlp push` updates the
|
|
177
|
+
> plugin with that id; without one it creates a *new* plugin on every run.
|
|
178
|
+
> Projects made with `trmnlp clone` or `trmnlp pull` already have it.
|
|
179
|
+
|
|
124
180
|
## Running trmnlp
|
|
125
181
|
|
|
126
182
|
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.
|
|
@@ -336,6 +392,21 @@ bin/rake
|
|
|
336
392
|
|
|
337
393
|
Specs run under SimpleCov; a coverage report is written to `coverage/`.
|
|
338
394
|
|
|
395
|
+
## Releasing
|
|
396
|
+
|
|
397
|
+
Releases are automated. The [`Release` workflow](.github/workflows/release.yaml)
|
|
398
|
+
fires whenever `lib/trmnlp/version.rb` changes on `main`, then tags the commit,
|
|
399
|
+
publishes the gem to RubyGems, and pushes the multi-arch Docker image. Each step
|
|
400
|
+
is idempotent, so the workflow is safe to re-run after a partial failure.
|
|
401
|
+
|
|
402
|
+
To cut a release:
|
|
403
|
+
|
|
404
|
+
1. Bump the version in `lib/trmnlp/version.rb`.
|
|
405
|
+
2. Run `bundle install` so `Gemfile.lock` picks up the new version.
|
|
406
|
+
3. Commit and merge to `main` — the workflow does the rest.
|
|
407
|
+
|
|
408
|
+
By convention, add a matching `CHANGELOG.md` entry in the same change.
|
|
409
|
+
|
|
339
410
|
## Contributing
|
|
340
411
|
|
|
341
412
|
Bug reports and pull requests are welcome on GitHub at https://github.com/usetrmnl/trmnlp.
|
data/lib/trmnlp/cli.rb
CHANGED
|
@@ -22,7 +22,7 @@ module TRMNLP
|
|
|
22
22
|
method_option :png, type: :boolean, default: false, desc: 'Also render a PNG per view'
|
|
23
23
|
method_option :width, type: :numeric, desc: 'PNG width in pixels (with --png)'
|
|
24
24
|
method_option :height, type: :numeric, desc: 'PNG height in pixels (with --png)'
|
|
25
|
-
method_option :color_depth, type: :numeric, desc: 'PNG bit depth: 1
|
|
25
|
+
method_option :color_depth, type: :numeric, desc: 'PNG bit depth: 1-8 (with --png)'
|
|
26
26
|
def build
|
|
27
27
|
Commands::Build.run(options)
|
|
28
28
|
end
|
|
@@ -34,11 +34,13 @@ module TRMNLP
|
|
|
34
34
|
|
|
35
35
|
desc 'init NAME', 'Start a new plugin project'
|
|
36
36
|
method_option :skip_liquid, type: :boolean, default: false, desc: 'Skip generating liquid templates'
|
|
37
|
+
method_option :skip_git, type: :boolean, default: false, desc: 'Skip initializing a git repository'
|
|
37
38
|
def init(name)
|
|
38
39
|
Commands::Init.run(options, name)
|
|
39
40
|
end
|
|
40
41
|
|
|
41
42
|
desc 'clone NAME ID', 'Copy a plugin project from TRMNL server'
|
|
43
|
+
method_option :skip_git, type: :boolean, default: false, desc: 'Skip initializing a git repository'
|
|
42
44
|
def clone(name, id)
|
|
43
45
|
Commands::Clone.run(options, name, id)
|
|
44
46
|
end
|
|
@@ -7,7 +7,7 @@ require_relative 'pull'
|
|
|
7
7
|
module TRMNLP
|
|
8
8
|
module Commands
|
|
9
9
|
class Clone < Base
|
|
10
|
-
Options = Data.define(:dir, :quiet)
|
|
10
|
+
Options = Data.define(:dir, :quiet, :skip_git)
|
|
11
11
|
|
|
12
12
|
def call(directory_name, id)
|
|
13
13
|
authenticate!
|
|
@@ -15,7 +15,7 @@ module TRMNLP
|
|
|
15
15
|
destination_path = Pathname.new(options.dir).join(directory_name)
|
|
16
16
|
raise DirectoryExists, "directory #{destination_path} already exists, aborting" if destination_path.exist?
|
|
17
17
|
|
|
18
|
-
Init.run({ dir: options.dir, skip_liquid: true, quiet: true }, directory_name)
|
|
18
|
+
Init.run({ dir: options.dir, skip_liquid: true, quiet: true, skip_git: options.skip_git }, directory_name)
|
|
19
19
|
|
|
20
20
|
Pull.run({ dir: destination_path.to_s, force: true, id: id })
|
|
21
21
|
|
data/lib/trmnlp/commands/init.rb
CHANGED
|
@@ -7,7 +7,7 @@ require_relative 'base'
|
|
|
7
7
|
module TRMNLP
|
|
8
8
|
module Commands
|
|
9
9
|
class Init < Base
|
|
10
|
-
Options = Data.define(:dir, :quiet, :skip_liquid)
|
|
10
|
+
Options = Data.define(:dir, :quiet, :skip_liquid, :skip_git)
|
|
11
11
|
|
|
12
12
|
def call(name)
|
|
13
13
|
destination_dir = Pathname.new(options.dir).join(name)
|
|
@@ -17,7 +17,9 @@ module TRMNLP
|
|
|
17
17
|
destination_dir.mkpath
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
# NOTE: FNM_DOTMATCH so the glob descends into hidden template
|
|
21
|
+
# directories (e.g. .github/); without it those files are skipped.
|
|
22
|
+
template_dir.glob('**/{*,.*}', File::FNM_DOTMATCH).each do |source_pathname|
|
|
21
23
|
next if source_pathname.directory?
|
|
22
24
|
next if options.skip_liquid && source_pathname.extname == '.liquid'
|
|
23
25
|
|
|
@@ -41,6 +43,8 @@ module TRMNLP
|
|
|
41
43
|
destination_pathname.chmod(destination_pathname.stat.mode | 0o200)
|
|
42
44
|
end
|
|
43
45
|
|
|
46
|
+
init_git_repo(destination_dir) unless options.skip_git
|
|
47
|
+
|
|
44
48
|
reporter.info <<~HEREDOC
|
|
45
49
|
|
|
46
50
|
To start the local server:
|
|
@@ -58,6 +62,13 @@ module TRMNLP
|
|
|
58
62
|
private
|
|
59
63
|
|
|
60
64
|
def template_dir = paths.templates_dir.join('init')
|
|
65
|
+
|
|
66
|
+
# Make the scaffold a Git repository on `main` so it's ready to push
|
|
67
|
+
# to GitHub (the workflow's `branches: [main]` trigger requires it,
|
|
68
|
+
# regardless of the host's init.defaultBranch).
|
|
69
|
+
# Does nothing when git is unavailable — `system` returns nil rather
|
|
70
|
+
# than raising, so the scaffold itself still succeeds.
|
|
71
|
+
def init_git_repo(dir) = system('git', 'init', '-q', '-b', 'main', dir.to_s)
|
|
61
72
|
end
|
|
62
73
|
end
|
|
63
74
|
end
|
|
@@ -44,9 +44,13 @@ module TRMNLP
|
|
|
44
44
|
|
|
45
45
|
def pinned? = @pinned
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
# Both a pinned and an unpinned ("latest") version resolve to a
|
|
48
|
+
# concrete release here — #number is never the literal "latest" — so a
|
|
49
|
+
# local preview renders the same bundle as the hosted service instead
|
|
50
|
+
# of drifting onto a new release the moment one ships.
|
|
51
|
+
def css_url = "#{@asset_host}/css/#{number}/plugins.css"
|
|
48
52
|
|
|
49
|
-
def js_url = "#{@asset_host}/js/#{
|
|
53
|
+
def js_url = "#{@asset_host}/js/#{number}/plugins.js"
|
|
50
54
|
|
|
51
55
|
def ==(other) = other.is_a?(self.class) && number == other.number
|
|
52
56
|
|
|
@@ -59,11 +63,5 @@ module TRMNLP
|
|
|
59
63
|
def as_json(*) = number
|
|
60
64
|
|
|
61
65
|
def to_s = number
|
|
62
|
-
|
|
63
|
-
private
|
|
64
|
-
|
|
65
|
-
# When pinned, requests assets at /css/<version>/plugins.css to lock
|
|
66
|
-
# behavior; otherwise hit /css/latest/ for live updates.
|
|
67
|
-
def path_segment = pinned? ? @number : 'latest'
|
|
68
66
|
end
|
|
69
67
|
end
|
|
@@ -24,8 +24,8 @@ module TRMNLP
|
|
|
24
24
|
def pass? = static_image_urls.all? { |url| reachable?(url) }
|
|
25
25
|
|
|
26
26
|
def static_image_urls
|
|
27
|
-
source.
|
|
28
|
-
.
|
|
27
|
+
source.all_markup
|
|
28
|
+
.scan(/<img[^>]+src\s*=\s*["']([^"']+)["']/i).flatten
|
|
29
29
|
.map(&:strip)
|
|
30
30
|
.reject { |src| src.empty? || src.include?('{{') || src.start_with?('data:') }
|
|
31
31
|
end
|
|
@@ -6,7 +6,8 @@ module TRMNLP
|
|
|
6
6
|
module Lint
|
|
7
7
|
module Checks
|
|
8
8
|
class WaitsForDomLoad < Check
|
|
9
|
-
MESSAGE = 'JavaScript should listen for the DOMContentLoaded event,
|
|
9
|
+
MESSAGE = 'JavaScript should listen for the DOMContentLoaded event, ' \
|
|
10
|
+
'not window.onload or window.addEventListener("load")'
|
|
10
11
|
LEARN_MORE = 'https://help.trmnl.com/en/articles/9510536-private-plugins#h_db7030f8b8'
|
|
11
12
|
FORBIDDEN = ['window.onload', 'window.addeventlistener("load")',
|
|
12
13
|
"window.addeventlistener('load')"].freeze
|
data/lib/trmnlp/renderer.rb
CHANGED
|
@@ -59,9 +59,7 @@ module TRMNLP
|
|
|
59
59
|
TransformClient::Result.new(
|
|
60
60
|
stdout: parsed['stdout'] || '',
|
|
61
61
|
stderr: parsed['stderr'] || '',
|
|
62
|
-
|
|
63
|
-
# the separate `output` channel yet.
|
|
64
|
-
output: (parsed['output'].to_s.empty? ? parsed['stdout'] : parsed['output']).to_s,
|
|
62
|
+
output: parsed['output'].to_s,
|
|
65
63
|
exit_code: parsed['exit_code'] || 0,
|
|
66
64
|
duration_ms: parsed['duration_ms'] || 0,
|
|
67
65
|
error: parsed['error']
|
|
@@ -9,8 +9,10 @@ module TRMNLP
|
|
|
9
9
|
# snippet supplied by the caller. Subprocess writes to a tempfile
|
|
10
10
|
# path, Http writes to FD 3 for the production daemon to capture.
|
|
11
11
|
#
|
|
12
|
-
# Mirrors the hosted serverless runtime's code-wrapping behavior
|
|
13
|
-
#
|
|
12
|
+
# Mirrors the hosted serverless runtime's code-wrapping behavior,
|
|
13
|
+
# parameterized on the per-backend output sink. PHP additionally
|
|
14
|
+
# carries a leading `<?php` tag the file-based Subprocess path
|
|
15
|
+
# needs; the daemon tolerates it, so parity holds.
|
|
14
16
|
#
|
|
15
17
|
# NOTE: `output_sink` is spliced verbatim into the generated script as
|
|
16
18
|
# executable code. It MUST be trmnlp-generated (see Subprocess#sink_for
|
|
@@ -17,9 +17,9 @@ module TRMNLP
|
|
|
17
17
|
|
|
18
18
|
# Assembles the merged data hash. The trmnl namespace is built first,
|
|
19
19
|
# layered with static_data / cached polled data / user_data_overrides,
|
|
20
|
-
# then piped through the transform. The trmnl namespace is
|
|
21
|
-
# after the transform so
|
|
22
|
-
#
|
|
20
|
+
# then piped through the transform. The whole trmnl namespace is
|
|
21
|
+
# re-applied after the transform so it survives even when the
|
|
22
|
+
# transform doesn't pass it through.
|
|
23
23
|
def call(device: {})
|
|
24
24
|
namespace = base_trmnl_data(device:)
|
|
25
25
|
merged = assemble(namespace)
|
data/lib/trmnlp/version.rb
CHANGED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
name: TRMNL
|
|
2
|
+
on:
|
|
3
|
+
pull_request:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
lint:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
steps:
|
|
11
|
+
- uses: actions/checkout@v6
|
|
12
|
+
- uses: ruby/setup-ruby@v1
|
|
13
|
+
with:
|
|
14
|
+
ruby-version: "4.0"
|
|
15
|
+
- run: gem install trmnl_preview
|
|
16
|
+
- run: trmnlp lint
|
|
17
|
+
|
|
18
|
+
push:
|
|
19
|
+
needs: lint
|
|
20
|
+
if: github.ref == 'refs/heads/main'
|
|
21
|
+
runs-on: ubuntu-latest
|
|
22
|
+
steps:
|
|
23
|
+
- uses: actions/checkout@v6
|
|
24
|
+
- uses: ruby/setup-ruby@v1
|
|
25
|
+
with:
|
|
26
|
+
ruby-version: "4.0"
|
|
27
|
+
- run: gem install trmnl_preview
|
|
28
|
+
- run: trmnlp push --force
|
|
29
|
+
env:
|
|
30
|
+
TRMNL_API_KEY: ${{ secrets.TRMNL_API_KEY }}
|
data/trmnl_preview.gemspec
CHANGED
|
@@ -21,17 +21,20 @@ Gem::Specification.new do |spec|
|
|
|
21
21
|
spec.metadata['rubygems_mfa_required'] = 'true'
|
|
22
22
|
|
|
23
23
|
spec.files = Dir.chdir(__dir__) do
|
|
24
|
-
[
|
|
24
|
+
files = [
|
|
25
25
|
'bin/**/*',
|
|
26
26
|
'db/**/*',
|
|
27
27
|
'lib/**/*',
|
|
28
|
-
'templates/**/{*,.*}',
|
|
29
28
|
'web/**/*',
|
|
30
29
|
'CHANGELOG.md',
|
|
31
30
|
'LICENSE.txt',
|
|
32
31
|
'README.md',
|
|
33
32
|
'trmnl_preview.gemspec'
|
|
34
33
|
].flat_map { |glob| Dir[glob] }
|
|
34
|
+
|
|
35
|
+
# FNM_DOTMATCH so the glob descends into the templates' hidden directories
|
|
36
|
+
# (e.g. .github/) — a plain Dir[] skips them and drops the file from the gem.
|
|
37
|
+
files + Dir.glob('templates/**/{*,.*}', File::FNM_DOTMATCH)
|
|
35
38
|
end
|
|
36
39
|
spec.bindir = 'bin'
|
|
37
40
|
spec.executables = ['trmnlp']
|
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.8.
|
|
4
|
+
version: 0.8.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Rockwell Schrock
|
|
@@ -319,6 +319,8 @@ files:
|
|
|
319
319
|
- lib/trmnlp/user_data_assembler.rb
|
|
320
320
|
- lib/trmnlp/version.rb
|
|
321
321
|
- lib/trmnlp/watcher.rb
|
|
322
|
+
- templates/init/.github/workflows/trmnl.yml
|
|
323
|
+
- templates/init/.gitignore
|
|
322
324
|
- templates/init/.trmnlp.yml
|
|
323
325
|
- templates/init/bin/trmnlp
|
|
324
326
|
- templates/init/src/full.liquid
|