theme 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gems +8 -0
- data/.gitignore +2 -0
- data/Makefile +44 -0
- data/lib/theme/assets/middleware.rb +133 -0
- data/lib/theme/assets/render.rb +45 -0
- data/lib/theme/assets.rb +82 -0
- data/lib/theme/component.rb +103 -0
- data/lib/theme/event.rb +13 -0
- data/lib/theme/events.rb +66 -0
- data/lib/theme/file.rb +52 -0
- data/lib/theme/mab.rb +5 -0
- data/lib/theme/middleware.rb +59 -0
- data/lib/theme/version.rb +1 -1
- data/lib/theme.rb +144 -2
- data/test/dummy/components/header.rb +62 -0
- data/test/dummy/components/some_component.rb +3 -0
- data/test/dummy/index.html +386 -0
- data/test/events_test.rb +30 -0
- data/test/helper.rb +5 -0
- data/test/theme_test.rb +56 -0
- data/theme.gemspec +5 -2
- metadata +76 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 254228666c499ec52897053c19a69dc1ac3cf10c
|
4
|
+
data.tar.gz: ecc08329901e61dcdbbae73a82a1ee87f7c342a2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bc532e11312b41cbbd2e0aa1bffeab09937543308aa0dddc5c6d56965233cf7ebe859e268be11130e41b7fd1ee409ef7340cc6aef7b5c221e724c0d57f43fa05
|
7
|
+
data.tar.gz: 56a8e8f3c276a3848ee5e6973de0edfe1ddeabb5b7d01da8175015fa40a512b9a660b1e8b519ea243a06603ccfbbbd97fdd21b3162103057fdec7a32d33eb161
|
data/.gems
ADDED
data/.gitignore
CHANGED
data/Makefile
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
GEMSPEC=$(shell ls *.gemspec | head -1)
|
2
|
+
VERSION=$(shell ruby -rubygems -e 'puts Gem::Specification.load("$(GEMSPEC)").version')
|
3
|
+
PROJECT=$(shell ruby -rubygems -e 'puts Gem::Specification.load("$(GEMSPEC)").name')
|
4
|
+
GEM=$(PROJECT)-$(VERSION).gem
|
5
|
+
|
6
|
+
.PHONY: install package publish test server $(GEM)
|
7
|
+
|
8
|
+
define install_bs
|
9
|
+
which bs || (wget https://raw.githubusercontent.com/educabilia/bs/master/bin/bs && chmod +x bs && sudo mv bs /usr/local/bin)
|
10
|
+
|
11
|
+
@if [ -s .gs ]; then \
|
12
|
+
true; \
|
13
|
+
else \
|
14
|
+
mkdir .gs; \
|
15
|
+
touch .env; \
|
16
|
+
echo 'GEM_HOME=$$(pwd)/.gs' >> .env; \
|
17
|
+
echo 'GEM_PATH=$$(pwd)/.gs' >> .env; \
|
18
|
+
echo 'PATH=$$(pwd)/.gs/bin:$$PATH' >> .env; \
|
19
|
+
echo 'RACK_ENV=development' >> .env; \
|
20
|
+
fi;
|
21
|
+
|
22
|
+
bs gem list dep-cj -i || bs gem install dep-cj
|
23
|
+
bs gem list cutest-cj -i || bs gem install cutest-cj
|
24
|
+
bs gem list pry -i || bs gem install pry
|
25
|
+
bs gem list awesome_print -i || bs gem install awesome_print
|
26
|
+
endef
|
27
|
+
|
28
|
+
install:
|
29
|
+
$(call install_bs)
|
30
|
+
bs dep install
|
31
|
+
bs gem cleanup
|
32
|
+
|
33
|
+
test:
|
34
|
+
bs env $$(cat .env.test) cutest test/**/*_test.rb
|
35
|
+
|
36
|
+
package: $(GEM)
|
37
|
+
|
38
|
+
# Always build the gem
|
39
|
+
$(GEM):
|
40
|
+
gem build $(PROJECT).gemspec
|
41
|
+
|
42
|
+
publish: $(GEM)
|
43
|
+
gem push $(GEM)
|
44
|
+
make clean
|
@@ -0,0 +1,133 @@
|
|
1
|
+
require 'rack/mime'
|
2
|
+
require 'open-uri'
|
3
|
+
|
4
|
+
module Theme
|
5
|
+
module Assets
|
6
|
+
class Middleware
|
7
|
+
attr_reader :app, :env, :res
|
8
|
+
|
9
|
+
def initialize(app)
|
10
|
+
@app = app
|
11
|
+
end
|
12
|
+
|
13
|
+
def call env
|
14
|
+
dup.call! env
|
15
|
+
end
|
16
|
+
|
17
|
+
def call! env
|
18
|
+
@env = env
|
19
|
+
|
20
|
+
if assets_path
|
21
|
+
render_assets
|
22
|
+
else
|
23
|
+
res
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def res
|
30
|
+
@res ||= begin
|
31
|
+
if not assets_path
|
32
|
+
app.call(req.env)
|
33
|
+
else
|
34
|
+
Cuba::Response.new
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def req
|
40
|
+
@req ||= Rack::Request.new env
|
41
|
+
end
|
42
|
+
|
43
|
+
def assets_path
|
44
|
+
path[Regexp.new("^#{Theme.config.asset_url}($|.*)")]
|
45
|
+
end
|
46
|
+
|
47
|
+
def path
|
48
|
+
env['PATH_INFO']
|
49
|
+
end
|
50
|
+
|
51
|
+
def type
|
52
|
+
if matched = path.match(/(?<=#{Theme.config.asset_url}\/).*(?=\/)/)
|
53
|
+
matched[0]
|
54
|
+
else
|
55
|
+
''
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def name
|
60
|
+
@name ||= begin
|
61
|
+
cleaned = path.gsub(/\.#{ext}$/, '')
|
62
|
+
cleaned = cleaned.gsub(/^#{Theme.config.asset_url}\//, '')
|
63
|
+
cleaned = cleaned.gsub(/^#{type}\//, '')
|
64
|
+
cleaned
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def ext
|
69
|
+
if matched = path.match(/(?<=\.).*$/)
|
70
|
+
matched[0]
|
71
|
+
else
|
72
|
+
false
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def render_assets
|
77
|
+
case type
|
78
|
+
when 'css', 'stylesheet', 'stylesheets'
|
79
|
+
content_type = 'text/css; charset=utf-8'
|
80
|
+
when 'js', 'javascript', 'javascripts'
|
81
|
+
content_type = 'text/javascript; charset=utf-8'
|
82
|
+
else
|
83
|
+
content_type = Rack::Mime.mime_type ext
|
84
|
+
end
|
85
|
+
|
86
|
+
res.headers.merge!({
|
87
|
+
"Content-Type" => content_type,
|
88
|
+
"Cache-Control" => 'public, max-age=2592000, no-transform',
|
89
|
+
'Connection' => 'keep-alive',
|
90
|
+
'Age' => '25637',
|
91
|
+
'Strict-Transport-Security' => 'max-age=31536000',
|
92
|
+
'Content-Disposition' => 'inline'
|
93
|
+
})
|
94
|
+
|
95
|
+
if name == "all-#{sha}"
|
96
|
+
@name = 'dominate-compiled'
|
97
|
+
res.write render_single_file
|
98
|
+
elsif name == 'all'
|
99
|
+
res.write render_all_files
|
100
|
+
else
|
101
|
+
res.write render_single_file
|
102
|
+
end
|
103
|
+
|
104
|
+
res.finish
|
105
|
+
end
|
106
|
+
|
107
|
+
def render_all_files
|
108
|
+
content = ''
|
109
|
+
files = Theme.config.assets[ext]
|
110
|
+
path = "#{Theme.config.asset_path}/#{type}"
|
111
|
+
|
112
|
+
files.each do |file|
|
113
|
+
if file[/^http/]
|
114
|
+
content += open(file).string
|
115
|
+
else
|
116
|
+
content += Theme.load_file("#{path}/#{file}")
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
content
|
121
|
+
end
|
122
|
+
|
123
|
+
def render_single_file
|
124
|
+
path = "#{Theme.config.asset_path}/#{type}"
|
125
|
+
Theme.load_file "#{path}/#{name}.#{ext}"
|
126
|
+
end
|
127
|
+
|
128
|
+
def sha
|
129
|
+
Thread.current[:_sha] ||= (Theme.config.sha || `git rev-parse HEAD`.strip)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Theme
|
2
|
+
module Assets
|
3
|
+
module Render
|
4
|
+
def self.setup app
|
5
|
+
app.settings[:render] ||= {}
|
6
|
+
load_engines
|
7
|
+
end
|
8
|
+
|
9
|
+
def view file, options = {}
|
10
|
+
path = "#{settings[:render][:views] || Theme.config.view_path}"
|
11
|
+
Theme.load_file "#{path}/#{file}", options, self
|
12
|
+
end
|
13
|
+
|
14
|
+
def render file, options = {}
|
15
|
+
path = "#{settings[:render][:views] || Theme.config.view_path}"
|
16
|
+
layout_path = settings[:layout_path] || Theme.config.layout_path
|
17
|
+
layout = "#{layout_path}/#{settings[:render][:layout] || Theme.config.layout}"
|
18
|
+
content = Theme.load_file "#{path}/#{file}", options, self
|
19
|
+
options[:content] = content
|
20
|
+
Theme.load_file layout, options, self
|
21
|
+
end
|
22
|
+
|
23
|
+
def partial file, options = {}
|
24
|
+
file.gsub! PARTIAL_REGEX, '_\1'
|
25
|
+
path = "#{settings[:render][:views] || Theme.config.view_path}"
|
26
|
+
Theme.load_file "#{path}/#{file}", options, self
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def self.load_engines
|
32
|
+
if defined? Slim
|
33
|
+
Slim::Engine.set_default_options \
|
34
|
+
disable_escape: true,
|
35
|
+
use_html_safe: true,
|
36
|
+
disable_capture: false
|
37
|
+
|
38
|
+
if ENV['RACK_ENV'] == 'development'
|
39
|
+
Slim::Engine.set_default_options pretty: true
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/theme/assets.rb
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'theme/mab'
|
2
|
+
|
3
|
+
module Theme
|
4
|
+
module Assets
|
5
|
+
autoload :Middleware, 'theme/assets/middleware'
|
6
|
+
autoload :Render, 'theme/assets/render'
|
7
|
+
|
8
|
+
class << self
|
9
|
+
def setup app
|
10
|
+
app.plugin Render
|
11
|
+
app.use Middleware
|
12
|
+
end
|
13
|
+
|
14
|
+
def css_assets options = {}
|
15
|
+
options = {
|
16
|
+
'data-turbolinks-track' => 'true',
|
17
|
+
rel: 'stylesheet',
|
18
|
+
type: 'text/css',
|
19
|
+
media: 'all'
|
20
|
+
}.merge options
|
21
|
+
|
22
|
+
url = Theme.config.asset_url
|
23
|
+
|
24
|
+
if Theme.config.assets_compiled
|
25
|
+
options[:href] = "#{url}/css/all-#{sha}.css"
|
26
|
+
else
|
27
|
+
options[:href] = "#{url}/css/all.css"
|
28
|
+
end
|
29
|
+
|
30
|
+
mab { link options }
|
31
|
+
end
|
32
|
+
|
33
|
+
def js_assets options = {}
|
34
|
+
options = {
|
35
|
+
'data-turbolinks-track' => 'true',
|
36
|
+
}.merge options
|
37
|
+
|
38
|
+
url = Theme.config.asset_url
|
39
|
+
|
40
|
+
if Theme.config.assets_compiled
|
41
|
+
options[:src] = "#{url}/js/all-#{sha}.js"
|
42
|
+
else
|
43
|
+
options[:src] = "#{url}/js/all.js"
|
44
|
+
end
|
45
|
+
|
46
|
+
mab { script options }
|
47
|
+
end
|
48
|
+
|
49
|
+
def compile
|
50
|
+
Theme.config.assets.to_h.each do |type, assets|
|
51
|
+
content = ''
|
52
|
+
|
53
|
+
if assets.length > 0
|
54
|
+
type_path = "#{Theme.config.asset_path}/#{Theme.config[:"asset_#{type}_folder"]}"
|
55
|
+
assets.each do |file|
|
56
|
+
path = "#{type_path}/#{file}"
|
57
|
+
content += Theme.load_file path
|
58
|
+
end
|
59
|
+
tmp_path = "#{type_path}/tmp.dominate-compiled.#{type}"
|
60
|
+
File.write tmp_path, content
|
61
|
+
system "minify #{tmp_path} > #{type_path}/dominate-compiled.#{type}"
|
62
|
+
File.delete tmp_path
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def css_assets options = {}
|
69
|
+
Theme::Assets.css_assets options
|
70
|
+
end
|
71
|
+
|
72
|
+
def js_assets options = {}
|
73
|
+
Theme::Assets.js_assets options
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def sha
|
79
|
+
Thread.current[:_sha] ||= (Theme.config.sha || `git rev-parse HEAD`.strip)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'delegate'
|
2
|
+
require 'hashr'
|
3
|
+
|
4
|
+
Hashr.raise_missing_keys = true
|
5
|
+
|
6
|
+
module Theme
|
7
|
+
class Component < SimpleDelegator
|
8
|
+
include Theme::Events
|
9
|
+
|
10
|
+
attr_reader :instance
|
11
|
+
|
12
|
+
def initialize instance = false
|
13
|
+
@instance = instance
|
14
|
+
@node = self.class.node.clone if self.class.node
|
15
|
+
@name = self.class.name
|
16
|
+
|
17
|
+
instance.instance_variables.each do |name|
|
18
|
+
instance_variable_set name, instance.instance_variable_get(name)
|
19
|
+
end
|
20
|
+
|
21
|
+
super instance
|
22
|
+
end
|
23
|
+
|
24
|
+
class << self
|
25
|
+
attr_reader :html, :path, :id
|
26
|
+
attr_accessor :node
|
27
|
+
|
28
|
+
def id name
|
29
|
+
Theme.config.components[name] = self.to_s
|
30
|
+
@id = name
|
31
|
+
end
|
32
|
+
|
33
|
+
def src path
|
34
|
+
if path[/^\./]
|
35
|
+
@path = path
|
36
|
+
else
|
37
|
+
@path = "#{Theme.config.path}/#{path}"
|
38
|
+
end
|
39
|
+
|
40
|
+
@html = Theme.load_file @path
|
41
|
+
end
|
42
|
+
|
43
|
+
def dom location
|
44
|
+
node = Theme.cache.dom.fetch(path) do
|
45
|
+
n = Nokogiri::HTML html
|
46
|
+
Theme.cache.dom[path] = n
|
47
|
+
end
|
48
|
+
|
49
|
+
if location.is_a? String
|
50
|
+
@node = node.at location
|
51
|
+
else
|
52
|
+
@node = node.send location.keys.first, location.values.last
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def clean &block
|
57
|
+
block.call node
|
58
|
+
end
|
59
|
+
alias :setup :clean
|
60
|
+
end
|
61
|
+
|
62
|
+
attr_accessor :node
|
63
|
+
|
64
|
+
def method_missing method, *args, &block
|
65
|
+
# respond_to?(symbol, include_all=false)
|
66
|
+
if instance.respond_to? method, true
|
67
|
+
instance.send method, *args, &block
|
68
|
+
else
|
69
|
+
super
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def node
|
74
|
+
@node ||= self.class.node.clone
|
75
|
+
end
|
76
|
+
|
77
|
+
def render meth = 'display', options = {}
|
78
|
+
if method(meth).parameters.length > 0
|
79
|
+
opts = Hashr.new(options)
|
80
|
+
resp = send meth, opts
|
81
|
+
else
|
82
|
+
resp = send meth
|
83
|
+
end
|
84
|
+
|
85
|
+
options.clear
|
86
|
+
|
87
|
+
if resp.is_a? Nokogiri::XML::Element
|
88
|
+
resp.to_html
|
89
|
+
else
|
90
|
+
resp
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def set_locals options
|
95
|
+
options.to_h.each do |key, value|
|
96
|
+
(class << self; self; end).send(:attr_accessor, key.to_sym)
|
97
|
+
instance_variable_set("@#{key}", value)
|
98
|
+
end
|
99
|
+
|
100
|
+
self
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
data/lib/theme/event.rb
ADDED
data/lib/theme/events.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
module Theme
|
2
|
+
module Events
|
3
|
+
def self.included(other)
|
4
|
+
other.extend(Macros)
|
5
|
+
end
|
6
|
+
|
7
|
+
def add_listener(listener)
|
8
|
+
(@listeners ||= []) << listener
|
9
|
+
end
|
10
|
+
|
11
|
+
def notify_listeners(event, *args)
|
12
|
+
id = self.class.instance_variable_get :@id
|
13
|
+
|
14
|
+
(@listeners || []).each do |listener|
|
15
|
+
if id
|
16
|
+
listener.trigger(:"#{id}_#{event}", *args)
|
17
|
+
else
|
18
|
+
listener.trigger(event, *args)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def trigger(name, options = {})
|
24
|
+
if self.class._event_blocks && callback = self.class._event_blocks[name]
|
25
|
+
if callback.is_a? Proc
|
26
|
+
callback.call options
|
27
|
+
else
|
28
|
+
if method(callback).parameters.length > 0
|
29
|
+
send callback, options
|
30
|
+
else
|
31
|
+
send callback
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
notify_listeners(name, options)
|
37
|
+
end
|
38
|
+
|
39
|
+
module Macros
|
40
|
+
attr_accessor :_event_blocks, :_listeners
|
41
|
+
|
42
|
+
def on_event(name, options = {}, &block)
|
43
|
+
if id = options[:for]
|
44
|
+
(@_listeners ||= []) << id
|
45
|
+
name = :"#{id}_#{name}"
|
46
|
+
end
|
47
|
+
|
48
|
+
@_event_blocks ||= {}
|
49
|
+
@_event_blocks[name] = options.fetch(:use) { block }
|
50
|
+
|
51
|
+
mod = if const_defined?(:Events, false)
|
52
|
+
const_get(:Events)
|
53
|
+
else
|
54
|
+
new_mod = Module.new do
|
55
|
+
def self.to_s
|
56
|
+
"Events(#{instance_methods(false).join(', ')})"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
const_set(:Events, new_mod)
|
60
|
+
end
|
61
|
+
|
62
|
+
include mod
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
data/lib/theme/file.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
module Theme
|
2
|
+
module File
|
3
|
+
extend self
|
4
|
+
|
5
|
+
IMAGE_TYPES = %w(png gif jpg jpeg)
|
6
|
+
FONT_TYPES = %w(eot woff ttf svg)
|
7
|
+
STATIC_TYPES = %w(html js css map)
|
8
|
+
VIEW_TYPES = %w(html slim haml erb md markdown mkd mab)
|
9
|
+
|
10
|
+
def load path, c = {}, instance = self
|
11
|
+
cache = Theme.cache.file.fetch(path) {
|
12
|
+
template = false
|
13
|
+
|
14
|
+
ext = path[/\.[^.]*$/][1..-1]
|
15
|
+
|
16
|
+
if ext && ::File.file?(path)
|
17
|
+
if STATIC_TYPES.include? ext
|
18
|
+
template = Tilt::PlainTemplate.new nil, 1, outvar: '@_output', default_encoding: 'UTF-8' do |t|
|
19
|
+
::File.read(path)
|
20
|
+
end
|
21
|
+
elsif FONT_TYPES.include?(ext) || IMAGE_TYPES.include?(ext)
|
22
|
+
template = ::File.read path
|
23
|
+
else
|
24
|
+
template = Tilt.new path, 1, outvar: '@_output'
|
25
|
+
end
|
26
|
+
else
|
27
|
+
VIEW_TYPES.each do |type|
|
28
|
+
f = "#{path}.#{type}"
|
29
|
+
|
30
|
+
if ::File.file? f
|
31
|
+
template = Tilt.new f, 1, outvar: '@_output'
|
32
|
+
break
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
unless template
|
38
|
+
raise Theme::No::FileFound,
|
39
|
+
"Could't find file: #{path} with any of these extensions: #{VIEW_TYPES.join(', ')}."
|
40
|
+
end
|
41
|
+
|
42
|
+
template
|
43
|
+
}
|
44
|
+
|
45
|
+
if defined? cache.render
|
46
|
+
cache.render instance, c.to_h
|
47
|
+
else
|
48
|
+
cache.to_s
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/lib/theme/mab.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'rack/mime'
|
2
|
+
require 'open-uri'
|
3
|
+
|
4
|
+
module Theme
|
5
|
+
class Middleware
|
6
|
+
attr_reader :app, :env, :res
|
7
|
+
|
8
|
+
def initialize(app)
|
9
|
+
@app = app
|
10
|
+
end
|
11
|
+
|
12
|
+
def call env
|
13
|
+
dup.call! env
|
14
|
+
end
|
15
|
+
|
16
|
+
def call! env
|
17
|
+
@env = env
|
18
|
+
|
19
|
+
if component_path
|
20
|
+
render_component
|
21
|
+
else
|
22
|
+
res
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def res
|
29
|
+
@res ||= begin
|
30
|
+
if not component_path
|
31
|
+
app.call(req.env)
|
32
|
+
else
|
33
|
+
Cuba::Response.new
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def req
|
39
|
+
@req ||= Rack::Request.new env
|
40
|
+
end
|
41
|
+
|
42
|
+
def component_path
|
43
|
+
path[Regexp.new("^#{Theme.config.component_url}($|.*)")]
|
44
|
+
end
|
45
|
+
|
46
|
+
def path
|
47
|
+
env['PATH_INFO']
|
48
|
+
end
|
49
|
+
|
50
|
+
def render_component
|
51
|
+
app.instance_variable_set :@res, res
|
52
|
+
app.instance_variable_set :@req, req
|
53
|
+
name = req.params['component_name'].to_sym
|
54
|
+
event = req.params['component_event'].to_sym
|
55
|
+
app.theme_components[name].trigger event, Hashr.new(req.params)
|
56
|
+
res.finish
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
data/lib/theme/version.rb
CHANGED