Class: TRMNLPreview::Context

Inherits:
Object
  • Object
show all
Defined in:
lib/trmnl_preview/context.rb

Defined Under Namespace

Classes: ERBBinding

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(root, opts = {}) ⇒ Context

Returns a new instance of Context.



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/trmnl_preview/context.rb', line 15

def initialize(root, opts = {})
  config_path = File.join(root, 'config.toml')
  @user_views_dir = File.join(root, 'views')
  @temp_dir = File.join(root, 'tmp')
  @data_json_path = File.join(@temp_dir, 'data.json')

  unless File.exist?(config_path)
    raise "No config.toml found in #{root}"
  end

  unless Dir.exist?(@user_views_dir)
    raise "No views found at #{@user_views_dir}"
  end

  config = TomlRB.load_file(config_path)
  @strategy = config['strategy']
  @url = config['url']
  @polling_headers = config['polling_headers'] || {}
  @live_render = config['live_render'] != false
  @user_filters = config['custom_filters'] || []

  unless ['polling', 'webhook'].include?(@strategy)
    raise "Invalid strategy: #{strategy} (must be 'polling' or 'webhook')"
  end
  
  FileUtils.mkdir_p(@temp_dir)

  @liquid_environment = Liquid::Environment.build do |env|
    env.register_filter(CustomFilters)

    @user_filters.each do |module_name, relative_path|
      require File.join(root, relative_path)
      env.register_filter(Object.const_get(module_name))
    end
  end

  start_filewatcher_thread if @live_render
end

Instance Attribute Details

#live_renderObject (readonly)

Returns the value of attribute live_render.



13
14
15
# File 'lib/trmnl_preview/context.rb', line 13

def live_render
  @live_render
end

#strategyObject (readonly)

Returns the value of attribute strategy.



13
14
15
# File 'lib/trmnl_preview/context.rb', line 13

def strategy
  @strategy
end

#temp_dirObject (readonly)

Returns the value of attribute temp_dir.



13
14
15
# File 'lib/trmnl_preview/context.rb', line 13

def temp_dir
  @temp_dir
end

Instance Method Details

#on_view_change(&block) ⇒ Object



71
72
73
# File 'lib/trmnl_preview/context.rb', line 71

def on_view_change(&block)
  @view_change_callback = block
end

#poll_dataObject



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/trmnl_preview/context.rb', line 81

def poll_data
  if @url.nil?
    raise "URL is required for polling strategy"
  end

  print "Fetching #{@url}... "

  if @url.match?(/^https?:\/\//)
    payload = URI.open(@url, @polling_headers).read
  else
    payload = File.read(@url)
  end

  File.write(@data_json_path, payload)
  puts "got #{payload.size} bytes"

  user_data
end

#render_full_page(view) ⇒ Object



120
121
122
123
124
125
126
# File 'lib/trmnl_preview/context.rb', line 120

def render_full_page(view)
  page_erb_template = File.read(File.join(__dir__, '..', '..', 'web', 'views', 'render_html.erb'))
  
  ERB.new(page_erb_template).result(ERBBinding.new(view).get_binding do
    render_template(view)
  end)
end

#render_template(view) ⇒ Object



108
109
110
111
112
113
114
115
116
117
118
# File 'lib/trmnl_preview/context.rb', line 108

def render_template(view)
    path = view_path(view)
    unless File.exist?(path)
      return "Missing plugin template: views/#{view}.liquid"
    end

    user_template = Liquid::Template.parse(File.read(path), environment: @liquid_environment)
    user_template.render(user_data)
rescue StandardError => e
  e.message
end

#set_data(payload) ⇒ Object



100
101
102
# File 'lib/trmnl_preview/context.rb', line 100

def set_data(payload)
  File.write(@data_json_path, payload)
end

#start_filewatcher_threadObject



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/trmnl_preview/context.rb', line 54

def start_filewatcher_thread
  Thread.new do
    loop do
      begin
        Filewatcher.new(@user_views_dir).watch do |changes|
          views = changes.map { |path, _change| File.basename(path, '.liquid') }
          views.each do |view|
            @view_change_callback.call(view) if @view_change_callback
          end
        end
      rescue => e
        puts "Error during live render: #{e}"
      end
    end
  end
end

#user_dataObject



75
76
77
78
79
# File 'lib/trmnl_preview/context.rb', line 75

def user_data
  data = JSON.parse(File.read(@data_json_path))
  data = { data: data } if data.is_a?(Array) # per TRMNL docs, bare array is wrapped in 'data' key
  data
end

#view_path(view) ⇒ Object



104
105
106
# File 'lib/trmnl_preview/context.rb', line 104

def view_path(view)
  File.join(@user_views_dir, "#{view}.liquid")
end