trmnl_preview 0.3.2 → 0.4.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 +32 -0
- data/README.md +46 -17
- data/bin/trmnlp +14 -0
- data/lib/trmnlp/api_client.rb +62 -0
- data/lib/{trmnl_preview → trmnlp}/app.rb +24 -12
- data/lib/trmnlp/cli.rb +51 -0
- data/lib/trmnlp/commands/base.rb +23 -0
- data/lib/trmnlp/commands/build.rb +22 -0
- data/lib/trmnlp/commands/login.rb +25 -0
- data/lib/trmnlp/commands/pull.rb +45 -0
- data/lib/trmnlp/commands/push.rb +43 -0
- data/lib/trmnlp/commands/serve.rb +25 -0
- data/lib/trmnlp/commands.rb +1 -0
- data/lib/trmnlp/config/app.rb +39 -0
- data/lib/trmnlp/config/plugin.rb +74 -0
- data/lib/trmnlp/config/project.rb +47 -0
- data/lib/trmnlp/config.rb +15 -0
- data/lib/trmnlp/context.rb +211 -0
- data/lib/{trmnl_preview → trmnlp}/custom_filters.rb +2 -1
- data/lib/trmnlp/paths.rb +50 -0
- data/lib/{trmnl_preview → trmnlp}/screen_generator.rb +1 -1
- data/lib/trmnlp/version.rb +5 -0
- data/lib/trmnlp.rb +13 -0
- data/trmnl_preview.gemspec +19 -12
- data/web/public/index.js +5 -1
- data/web/views/index.erb +2 -0
- data/web/views/render_html.erb +1 -1
- metadata +87 -24
- data/.ruby-version +0 -1
- data/config.example.toml +0 -14
- data/docs/preview.png +0 -0
- data/exe/trmnlp +0 -14
- data/lib/trmnl_preview/cmd/build.rb +0 -25
- data/lib/trmnl_preview/cmd/serve.rb +0 -31
- data/lib/trmnl_preview/cmd/usage.rb +0 -11
- data/lib/trmnl_preview/cmd/version.rb +0 -1
- data/lib/trmnl_preview/context.rb +0 -135
- data/lib/trmnl_preview/version.rb +0 -5
- data/lib/trmnl_preview.rb +0 -10
@@ -1,25 +0,0 @@
|
|
1
|
-
require 'optionparser'
|
2
|
-
|
3
|
-
require_relative '../context'
|
4
|
-
|
5
|
-
OptionParser.new do |opts|
|
6
|
-
opts.banner = "Usage: trmnlp build [directory]"
|
7
|
-
end.parse!
|
8
|
-
|
9
|
-
root = ARGV[1] || Dir.pwd
|
10
|
-
begin
|
11
|
-
context = TRMNLPreview::Context.new(root)
|
12
|
-
rescue StandardError => e
|
13
|
-
puts e.message
|
14
|
-
exit 1
|
15
|
-
end
|
16
|
-
|
17
|
-
context.poll_data
|
18
|
-
|
19
|
-
TRMNLPreview::VIEWS.each do |view|
|
20
|
-
output_path = File.join(context.temp_dir, "#{view}.html")
|
21
|
-
puts "Creating #{output_path}..."
|
22
|
-
File.write(output_path, context.render_full_page(view))
|
23
|
-
end
|
24
|
-
|
25
|
-
puts "Done!"
|
@@ -1,31 +0,0 @@
|
|
1
|
-
require 'optionparser'
|
2
|
-
|
3
|
-
options = {
|
4
|
-
bind: '127.0.0.1',
|
5
|
-
port: 4567
|
6
|
-
}
|
7
|
-
|
8
|
-
# Parse options BEFORE requiring the Sinatra app, since it has its own option-parsing behavior.
|
9
|
-
# This will remove the option items from ARGV, which is what we want.
|
10
|
-
OptionParser.new do |opts|
|
11
|
-
opts.banner = "Usage: trmnlp serve [directory] [options]"
|
12
|
-
|
13
|
-
opts.on("-b", "--bind [HOST]", "Bind to host address (default: 127.0.0.1)") do |host|
|
14
|
-
options[:bind] = host
|
15
|
-
end
|
16
|
-
|
17
|
-
opts.on("-p", "--port [PORT]", "Use port (default: 4567)") do |port|
|
18
|
-
options[:port] = port
|
19
|
-
end
|
20
|
-
end.parse!
|
21
|
-
|
22
|
-
# Must come AFTER parsing options
|
23
|
-
require_relative '../app'
|
24
|
-
|
25
|
-
# Now we can configure things
|
26
|
-
TRMNLPreview::App.set(:user_dir, ARGV[1] || Dir.pwd)
|
27
|
-
TRMNLPreview::App.set(:bind, options[:bind])
|
28
|
-
TRMNLPreview::App.set(:port, options[:port])
|
29
|
-
|
30
|
-
# Finally, start the app!
|
31
|
-
TRMNLPreview::App.run!
|
@@ -1 +0,0 @@
|
|
1
|
-
puts TRMNLPreview::VERSION
|
@@ -1,135 +0,0 @@
|
|
1
|
-
require 'erb'
|
2
|
-
require 'fileutils'
|
3
|
-
require 'filewatcher'
|
4
|
-
require 'json'
|
5
|
-
require 'liquid'
|
6
|
-
require 'open-uri'
|
7
|
-
require 'toml-rb'
|
8
|
-
|
9
|
-
require_relative 'custom_filters'
|
10
|
-
|
11
|
-
module TRMNLPreview
|
12
|
-
class Context
|
13
|
-
attr_reader :strategy, :temp_dir, :live_render
|
14
|
-
|
15
|
-
def initialize(root, opts = {})
|
16
|
-
config_path = File.join(root, 'config.toml')
|
17
|
-
@user_views_dir = File.join(root, 'views')
|
18
|
-
@temp_dir = File.join(root, 'tmp')
|
19
|
-
@data_json_path = File.join(@temp_dir, 'data.json')
|
20
|
-
|
21
|
-
unless File.exist?(config_path)
|
22
|
-
raise "No config.toml found in #{root}"
|
23
|
-
end
|
24
|
-
|
25
|
-
unless Dir.exist?(@user_views_dir)
|
26
|
-
raise "No views found at #{@user_views_dir}"
|
27
|
-
end
|
28
|
-
|
29
|
-
config = TomlRB.load_file(config_path)
|
30
|
-
@strategy = config['strategy']
|
31
|
-
@url = config['url']
|
32
|
-
@polling_headers = config['polling_headers'] || {}
|
33
|
-
@live_render = config['live_render'] != false
|
34
|
-
@user_filters = config['custom_filters'] || []
|
35
|
-
|
36
|
-
unless ['polling', 'webhook'].include?(@strategy)
|
37
|
-
raise "Invalid strategy: #{strategy} (must be 'polling' or 'webhook')"
|
38
|
-
end
|
39
|
-
|
40
|
-
FileUtils.mkdir_p(@temp_dir)
|
41
|
-
|
42
|
-
@liquid_environment = Liquid::Environment.build do |env|
|
43
|
-
env.register_filter(CustomFilters)
|
44
|
-
|
45
|
-
@user_filters.each do |module_name, relative_path|
|
46
|
-
require File.join(root, relative_path)
|
47
|
-
env.register_filter(Object.const_get(module_name))
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
start_filewatcher_thread if @live_render
|
52
|
-
end
|
53
|
-
|
54
|
-
def start_filewatcher_thread
|
55
|
-
Thread.new do
|
56
|
-
loop do
|
57
|
-
begin
|
58
|
-
Filewatcher.new(@user_views_dir).watch do |changes|
|
59
|
-
views = changes.map { |path, _change| File.basename(path, '.liquid') }
|
60
|
-
views.each do |view|
|
61
|
-
@view_change_callback.call(view) if @view_change_callback
|
62
|
-
end
|
63
|
-
end
|
64
|
-
rescue => e
|
65
|
-
puts "Error during live render: #{e}"
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
def on_view_change(&block)
|
72
|
-
@view_change_callback = block
|
73
|
-
end
|
74
|
-
|
75
|
-
def user_data
|
76
|
-
data = JSON.parse(File.read(@data_json_path))
|
77
|
-
data = { data: data } if data.is_a?(Array) # per TRMNL docs, bare array is wrapped in 'data' key
|
78
|
-
data
|
79
|
-
end
|
80
|
-
|
81
|
-
def poll_data
|
82
|
-
if @url.nil?
|
83
|
-
raise "URL is required for polling strategy"
|
84
|
-
end
|
85
|
-
|
86
|
-
print "Fetching #{@url}... "
|
87
|
-
|
88
|
-
if @url.match?(/^https?:\/\//)
|
89
|
-
payload = URI.open(@url, @polling_headers).read
|
90
|
-
else
|
91
|
-
payload = File.read(@url)
|
92
|
-
end
|
93
|
-
|
94
|
-
File.write(@data_json_path, payload)
|
95
|
-
puts "got #{payload.size} bytes"
|
96
|
-
|
97
|
-
user_data
|
98
|
-
end
|
99
|
-
|
100
|
-
def set_data(payload)
|
101
|
-
File.write(@data_json_path, payload)
|
102
|
-
end
|
103
|
-
|
104
|
-
def view_path(view)
|
105
|
-
File.join(@user_views_dir, "#{view}.liquid")
|
106
|
-
end
|
107
|
-
|
108
|
-
def render_template(view)
|
109
|
-
path = view_path(view)
|
110
|
-
unless File.exist?(path)
|
111
|
-
return "Missing plugin template: views/#{view}.liquid"
|
112
|
-
end
|
113
|
-
|
114
|
-
user_template = Liquid::Template.parse(File.read(path), environment: @liquid_environment)
|
115
|
-
user_template.render(user_data)
|
116
|
-
rescue StandardError => e
|
117
|
-
e.message
|
118
|
-
end
|
119
|
-
|
120
|
-
def render_full_page(view)
|
121
|
-
page_erb_template = File.read(File.join(__dir__, '..', '..', 'web', 'views', 'render_html.erb'))
|
122
|
-
|
123
|
-
ERB.new(page_erb_template).result(ERBBinding.new(view).get_binding do
|
124
|
-
render_template(view)
|
125
|
-
end)
|
126
|
-
end
|
127
|
-
|
128
|
-
private
|
129
|
-
|
130
|
-
class ERBBinding
|
131
|
-
def initialize(view) = @view = view
|
132
|
-
def get_binding = binding
|
133
|
-
end
|
134
|
-
end
|
135
|
-
end
|
data/lib/trmnl_preview.rb
DELETED