plezi 0.12.22 → 0.14.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +18 -0
- data/LICENSE.txt +17 -18
- data/README.md +54 -698
- data/Rakefile +7 -4
- data/bin/config.ru +22 -0
- data/{test → bin}/console +4 -6
- data/bin/hello_world +52 -0
- data/bin/setup +8 -0
- data/exe/plezi +145 -0
- data/lib/plezi.rb +24 -137
- data/lib/plezi/activation.rb +28 -0
- data/lib/plezi/api.rb +62 -0
- data/lib/plezi/controller/controller.rb +259 -0
- data/lib/plezi/controller/controller_class.rb +176 -0
- data/lib/plezi/controller/cookies.rb +40 -0
- data/lib/plezi/helpers.rb +60 -0
- data/lib/plezi/rake.rb +2 -24
- data/lib/plezi/render/erb.rb +34 -0
- data/lib/plezi/render/has_cache.rb +36 -0
- data/lib/plezi/render/markdown.rb +63 -0
- data/lib/plezi/render/render.rb +49 -0
- data/lib/plezi/render/sass.rb +55 -0
- data/lib/plezi/render/slim.rb +33 -0
- data/lib/plezi/router/adclient.rb +23 -0
- data/lib/plezi/router/assets.rb +67 -0
- data/lib/plezi/router/errors.rb +29 -0
- data/lib/plezi/router/route.rb +112 -0
- data/lib/plezi/router/router.rb +120 -0
- data/lib/plezi/version.rb +1 -1
- data/lib/plezi/websockets/message_dispatch.rb +91 -0
- data/lib/plezi/websockets/redis.rb +55 -0
- data/plezi.gemspec +25 -16
- data/resources/404.erb +5 -4
- data/resources/500.erb +5 -4
- data/resources/{500.html → 503.html} +8 -9
- data/resources/client.js +253 -0
- data/resources/config.ru +5 -36
- data/resources/ctrlr.rb +34 -0
- data/resources/gemfile +4 -0
- data/resources/mini_app.rb +28 -82
- data/resources/mini_exec +7 -0
- data/resources/mini_welcome_page.html +0 -0
- data/resources/procfile +3 -0
- data/resources/rakefile +4 -8
- data/resources/routes.rb +9 -26
- data/resources/{websockets.js → simple-client.js} +3 -3
- metadata +60 -85
- data/bin/plezi +0 -104
- data/docs/async_helpers.md +0 -245
- data/docs/controllers.md +0 -27
- data/docs/logging.md +0 -49
- data/docs/routes.md +0 -209
- data/docs/websockets.md +0 -213
- data/lib/plezi/builders/ac_model.rb +0 -59
- data/lib/plezi/builders/app_builder.rb +0 -137
- data/lib/plezi/builders/builder.rb +0 -43
- data/lib/plezi/builders/form_builder.rb +0 -27
- data/lib/plezi/common/api.rb +0 -92
- data/lib/plezi/common/cache.rb +0 -122
- data/lib/plezi/common/defer.rb +0 -21
- data/lib/plezi/common/dsl.rb +0 -94
- data/lib/plezi/common/redis.rb +0 -65
- data/lib/plezi/common/renderer.rb +0 -141
- data/lib/plezi/common/settings.rb +0 -52
- data/lib/plezi/handlers/controller_core.rb +0 -106
- data/lib/plezi/handlers/controller_magic.rb +0 -284
- data/lib/plezi/handlers/http_router.rb +0 -205
- data/lib/plezi/handlers/placebo.rb +0 -112
- data/lib/plezi/handlers/route.rb +0 -216
- data/lib/plezi/handlers/session.rb +0 -109
- data/lib/plezi/handlers/stubs.rb +0 -156
- data/lib/plezi/handlers/ws_identity.rb +0 -253
- data/lib/plezi/handlers/ws_object.rb +0 -308
- data/lib/plezi/helpers/http_sender.rb +0 -84
- data/lib/plezi/helpers/magic_helpers.rb +0 -104
- data/lib/plezi/helpers/mime_types.rb +0 -1995
- data/lib/plezi/oauth.rb +0 -5
- data/lib/plezi/oauth/auth_controller.rb +0 -229
- data/logo/dark.png +0 -0
- data/logo/light.png +0 -0
- data/logo/sign.png +0 -0
- data/resources/404.haml +0 -121
- data/resources/404.html +0 -124
- data/resources/404.slim +0 -120
- data/resources/500.haml +0 -120
- data/resources/500.slim +0 -120
- data/resources/Gemfile +0 -86
- data/resources/code.rb +0 -8
- data/resources/controller.rb +0 -142
- data/resources/database.yml +0 -33
- data/resources/db_ac_config.rb +0 -59
- data/resources/db_dm_config.rb +0 -51
- data/resources/db_sequel_config.rb +0 -33
- data/resources/en.yml +0 -204
- data/resources/haml_config.rb +0 -6
- data/resources/i18n_config.rb +0 -14
- data/resources/initialize.rb +0 -49
- data/resources/mini_exec.rb +0 -7
- data/resources/oauth_config.rb +0 -24
- data/resources/plezi_client.js +0 -198
- data/resources/plezi_websockets.html +0 -47
- data/resources/redis_config.rb +0 -42
- data/resources/slim_config.rb +0 -11
- data/resources/welcome_page.html +0 -272
- data/test/dispatch +0 -58
- data/test/hello_world +0 -13
- data/test/plezi_tests.rb +0 -581
@@ -0,0 +1,40 @@
|
|
1
|
+
module Plezi
|
2
|
+
module Controller
|
3
|
+
# The cookie jar class. Controllers have an instance of this class named `cookies`.
|
4
|
+
class Cookies < Hash
|
5
|
+
attr_reader :request, :response
|
6
|
+
def initialize(request, response)
|
7
|
+
@request = request
|
8
|
+
@response = response
|
9
|
+
end
|
10
|
+
|
11
|
+
# Reads a cookie from either the request cookie Hash or the new cookies Hash.
|
12
|
+
def[](key)
|
13
|
+
if key.is_a? Symbol
|
14
|
+
super(key) || super(key.to_s) || @request.cookies[key] || @request.cookies[key.to_s]
|
15
|
+
elsif key.is_a? String
|
16
|
+
super(key) || super(key.to_sym) || @request.cookies[key] || @request.cookies[key.to_sym]
|
17
|
+
else
|
18
|
+
super(key) || @request.cookies[key]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Sets (or deletes) a cookie. New cookies are placed in the new cookie Hash and are accessible only to the controller that created them.
|
23
|
+
def[]=(key, value)
|
24
|
+
if value.nil?
|
25
|
+
@response.delete_cookie key
|
26
|
+
delete key
|
27
|
+
if key.is_a? Symbol
|
28
|
+
delete key.to_s
|
29
|
+
elsif key.is_a? String
|
30
|
+
delete key.to_sym
|
31
|
+
end
|
32
|
+
return nil
|
33
|
+
end
|
34
|
+
@response.set_cookie key, value
|
35
|
+
value = value[:value] if value.is_a? Hash
|
36
|
+
super
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'plezi/activation'
|
2
|
+
require 'plezi/router/router'
|
3
|
+
|
4
|
+
module Plezi
|
5
|
+
module_function
|
6
|
+
|
7
|
+
# attempts to convert a string's encoding to UTF-8, but only when the string is a valid UTF-8 encoded string.
|
8
|
+
def try_utf8!(string, encoding = ::Encoding::UTF_8)
|
9
|
+
return nil unless string
|
10
|
+
string.force_encoding(::Encoding::ASCII_8BIT) unless string.force_encoding(encoding).valid_encoding?
|
11
|
+
string
|
12
|
+
end
|
13
|
+
|
14
|
+
# Sanitizes hash data, attempting to "rubyfy" any Hash Strings to reversible Ruby objects. i.e:
|
15
|
+
#
|
16
|
+
# {"go" => "<tag>home</tag>", "now" => "false", "count" => "8", "float" => "0.7", "empty" => ""}
|
17
|
+
#
|
18
|
+
# Will become:
|
19
|
+
#
|
20
|
+
# {go: "<tag>home</tag>", now: false, count: 8, float: "0.7", empty: nil}
|
21
|
+
#
|
22
|
+
# As you may notice, float Strings aren't "rubyfied". Any "rubyfied" object will revert back to the same String form using `to_s`.
|
23
|
+
def rubyfy(hash)
|
24
|
+
case hash
|
25
|
+
when Hash
|
26
|
+
cpy = Hash.new(&hash_proc_4symstr)
|
27
|
+
hash.each { |k, v| cpy[k.is_a?(String) ? k.to_sym : k] = rubyfy(v) }
|
28
|
+
hash = cpy
|
29
|
+
when String
|
30
|
+
hash = if hash.empty?
|
31
|
+
nil
|
32
|
+
elsif hash.to_i.to_s == hash
|
33
|
+
hash.to_i
|
34
|
+
elsif hash == 'true'.freeze
|
35
|
+
true
|
36
|
+
elsif hash == 'false'.freeze
|
37
|
+
false
|
38
|
+
else
|
39
|
+
ERB::Util.h try_utf8!(hash)
|
40
|
+
end
|
41
|
+
when Array
|
42
|
+
hash = hash.map { |i| rubyfy(i) }
|
43
|
+
end
|
44
|
+
hash
|
45
|
+
end
|
46
|
+
|
47
|
+
# Catches String/Symbol mixups. Add this to any Hash using Hash#default_proc=
|
48
|
+
def hash_proc_4symstr
|
49
|
+
@hash_proc_4symstr ||= proc do |hash, key|
|
50
|
+
case key
|
51
|
+
when String
|
52
|
+
tmp = key.to_sym
|
53
|
+
hash.key?(tmp) ? hash[tmp] : nil
|
54
|
+
when Symbol
|
55
|
+
tmp = key.to_s
|
56
|
+
hash.key?(tmp) ? hash[tmp] : nil
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/lib/plezi/rake.rb
CHANGED
@@ -1,24 +1,2 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
# Make sure the server doesn't start
|
5
|
-
Iodine.protocol = false
|
6
|
-
|
7
|
-
|
8
|
-
namespace :make do
|
9
|
-
# TODO: add ActiveRecord controller-model generator
|
10
|
-
|
11
|
-
# TODO: add Squel controller-model generator
|
12
|
-
|
13
|
-
end
|
14
|
-
# add console mode
|
15
|
-
desc "Same as `plezi c`: starts the application as a console, NOT a server."
|
16
|
-
task :console do
|
17
|
-
Kernel.exec "plezi c"
|
18
|
-
end
|
19
|
-
desc "Same as `rake console`: starts the application as a console, NOT a server."
|
20
|
-
task :c do
|
21
|
-
Kernel.exec "plezi c"
|
22
|
-
end
|
23
|
-
|
24
|
-
end
|
1
|
+
require 'plezi'
|
2
|
+
Plezi.no_autostart
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'plezi/render/has_cache' unless defined? ::Plezi::Base::HasStore
|
2
|
+
require 'erb'
|
3
|
+
module Plezi
|
4
|
+
module Base
|
5
|
+
module RenderERB
|
6
|
+
extend ::Plezi::Base::HasStore
|
7
|
+
|
8
|
+
module_function
|
9
|
+
|
10
|
+
def call(filename, context, &block)
|
11
|
+
return unless defined? ::ERB
|
12
|
+
return unless File.exist?(filename)
|
13
|
+
engine = load_engine(filename)
|
14
|
+
engine.result(context, &block)
|
15
|
+
end
|
16
|
+
if ENV['RACK_ENV'.freeze] == 'production'.freeze
|
17
|
+
def load_engine(filename)
|
18
|
+
engine = self[filename]
|
19
|
+
return engine if engine
|
20
|
+
self[filename] = ::ERB.new(::Plezi.try_utf8!(IO.binread(filename)))
|
21
|
+
end
|
22
|
+
else
|
23
|
+
def load_engine(filename)
|
24
|
+
engine, tm = self[filename]
|
25
|
+
return engine if engine && (tm == File.mtime(filename))
|
26
|
+
self[filename] = [(engine = ::ERB.new(::Plezi.try_utf8!(IO.binread(filename)))), File.mtime(filename)]
|
27
|
+
engine
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
::Plezi::Renderer.register :erb, ::Plezi::Base::RenderERB
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Plezi
|
2
|
+
module Base
|
3
|
+
# Provides a thread-safe caching engine
|
4
|
+
module HasCache
|
5
|
+
# initializes the cache
|
6
|
+
def self.extended(base)
|
7
|
+
base.instance_variable_set :@_lock, Mutex.new
|
8
|
+
base.instance_variable_set :@_cache, {}.dup
|
9
|
+
end
|
10
|
+
|
11
|
+
# Stores data in the cache
|
12
|
+
def store(key, value)
|
13
|
+
@_lock.synchronize { @_cache[key] = value }
|
14
|
+
end
|
15
|
+
alias []= store
|
16
|
+
# Retrieves data form the cache
|
17
|
+
def get(key)
|
18
|
+
@_lock.synchronize { @_cache[key] }
|
19
|
+
end
|
20
|
+
alias [] get
|
21
|
+
end
|
22
|
+
# Provides thread-specific caching engine, allowing lockless cache at the expenss of memory.
|
23
|
+
module HasStore
|
24
|
+
# Stores data in the cache
|
25
|
+
def store(key, value)
|
26
|
+
(Thread.current[(@_chache_name ||= object_id.to_s(16))] ||= {}.dup)[key] = value
|
27
|
+
end
|
28
|
+
alias []= store
|
29
|
+
# Retrieves data form the cache
|
30
|
+
def get(key)
|
31
|
+
(Thread.current[(@_chache_name ||= object_id.to_s(16))] ||= {}.dup)[key]
|
32
|
+
end
|
33
|
+
alias [] get
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'plezi/render/has_cache' unless defined? ::Plezi::Base::HasStore
|
2
|
+
# Redcarpet might not be available, if so, allow the require to throw it's exception.
|
3
|
+
unless defined?(::Redcarpet::Markdown)
|
4
|
+
begin
|
5
|
+
require('redcarpet')
|
6
|
+
rescue Exception
|
7
|
+
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
if defined?(Redcarpet::Markdown)
|
12
|
+
module Plezi
|
13
|
+
module Base
|
14
|
+
module RenderMarkDown
|
15
|
+
# A custom render engine that makes sure links to foriegn sites open in a new window/tab.
|
16
|
+
class NewPageLinksMDRenderer < Redcarpet::Render::HTML
|
17
|
+
# review's the link and renders the Html
|
18
|
+
def link(link, title, content)
|
19
|
+
"<a href=\"#{link}\"#{" target='_blank'" if link =~ /^http[s]?\:\/\//}#{" title=\"#{title}\"" if title}>#{content}</a>"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Extensions
|
24
|
+
MD_EXTENSIONS = { with_toc_data: true, strikethrough: true, autolink: true, fenced_code_blocks: true, no_intra_emphasis: true, tables: true, footnotes: true, underline: true, highlight: true }.freeze
|
25
|
+
# create a single gloabl renderer for all markdown files.
|
26
|
+
MD_RENDERER = Redcarpet::Markdown.new NewPageLinksMDRenderer.new(MD_EXTENSIONS.dup), MD_EXTENSIONS.dup
|
27
|
+
|
28
|
+
# create a single gloabl renderer for all markdown TOC.
|
29
|
+
MD_RENDERER_TOC = Redcarpet::Markdown.new Redcarpet::Render::HTML_TOC.new(MD_EXTENSIONS.dup), MD_EXTENSIONS.dup
|
30
|
+
|
31
|
+
extend ::Plezi::Base::HasStore
|
32
|
+
|
33
|
+
module_function
|
34
|
+
|
35
|
+
# renders the markdown file, if exists
|
36
|
+
def call(filename, _context)
|
37
|
+
return unless File.exist?(filename)
|
38
|
+
load_engine(filename)
|
39
|
+
end
|
40
|
+
|
41
|
+
if ENV['RACK_ENV'.freeze] == 'production'.freeze
|
42
|
+
# loads the rendered cache
|
43
|
+
def load_engine(filename)
|
44
|
+
engine = self[filename]
|
45
|
+
return engine if engine
|
46
|
+
data = IO.read filename
|
47
|
+
self[filename] = "<div class='toc'>#{::Plezi::Base::RenderMarkDown::MD_RENDERER_TOC.render(data)}</div>\n#{::Plezi::Base::RenderMarkDown::MD_RENDERER.render(data)}"
|
48
|
+
end
|
49
|
+
else
|
50
|
+
# loads the rendered cache
|
51
|
+
def load_engine(filename)
|
52
|
+
engine, tm = self[filename]
|
53
|
+
return engine if engine && tm == File.mtime(filename)
|
54
|
+
data = IO.read filename
|
55
|
+
(self[filename] = ["<div class='toc'>#{::Plezi::Base::RenderMarkDown::MD_RENDERER_TOC.render(data)}</div>\n#{::Plezi::Base::RenderMarkDown::MD_RENDERER.render(data)}", File.mtime(filename)])[0]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
::Plezi::Renderer.register :md, ::Plezi::Base::RenderMarkDown
|
63
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'thread'
|
2
|
+
|
3
|
+
module Plezi
|
4
|
+
module Renderer
|
5
|
+
@render_library = {}.dup
|
6
|
+
|
7
|
+
public
|
8
|
+
|
9
|
+
module_function
|
10
|
+
|
11
|
+
# Registers a rendering extention.
|
12
|
+
#
|
13
|
+
# Slim, Markdown, ERB and SASS are registered by default.
|
14
|
+
#
|
15
|
+
# extention:: a Symbol or String representing the extention of the file to be rendered. i.e. 'slim', 'md', 'erb', etc'
|
16
|
+
# handler :: a Proc or other object that answers to call(filename, context, &block) and returnes the rendered string.
|
17
|
+
# The block accepted by the handler is for chaining rendered actions (allowing for `yield` within templates)
|
18
|
+
# and the context is the object within which the rendering should be performed (if `binding` handling is
|
19
|
+
# supported by the engine). `filename` might not point to an existing or valid file.
|
20
|
+
#
|
21
|
+
# If a block is passed to the `register_hook` method with no handler defined, it will act as the handler.
|
22
|
+
def register(extention, handler = nil, &block)
|
23
|
+
handler ||= block
|
24
|
+
raise 'Handler or block required.' unless handler
|
25
|
+
@render_library[extention.to_s] = handler
|
26
|
+
handler
|
27
|
+
end
|
28
|
+
|
29
|
+
# Removes a registered render extention
|
30
|
+
def remove(extention)
|
31
|
+
@render_library.delete extention.to_s
|
32
|
+
end
|
33
|
+
|
34
|
+
# Attempts to render the requested file (i.e. `'index.html'`) using all known rendering handlers.
|
35
|
+
def render(base_filename, context = (Object.new.instance_eval { binding }), &block)
|
36
|
+
ret = nil
|
37
|
+
@render_library.each { |ext, handler| ret = handler.call("#{base_filename}.#{ext}".freeze, context, &block); return ret if ret; }
|
38
|
+
ret
|
39
|
+
end
|
40
|
+
# Renderer.register :haml do |filename, context, &block|
|
41
|
+
# next unless defined? ::Haml
|
42
|
+
# (Plezi.cache_needs_update?(filename) ? Plezi.cache_data(filename, Haml::Engine.new(Plezi::Base::Helpers.try_utf8!(IO.binread(filename)))) : (Plezi.get_cached filename)).render(context.receiver, &block)
|
43
|
+
# end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
require 'plezi/render/slim.rb'
|
48
|
+
require 'plezi/render/markdown.rb'
|
49
|
+
require 'plezi/render/erb.rb'
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'thread'
|
2
|
+
require 'plezi/render/has_cache'
|
3
|
+
# Redcarpet might not be available, if so, allow the require to throw it's exception.
|
4
|
+
unless defined?(::Sass)
|
5
|
+
begin
|
6
|
+
require('sass')
|
7
|
+
rescue Exception
|
8
|
+
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
if defined?(::Sass)
|
13
|
+
|
14
|
+
module Plezi
|
15
|
+
module Base
|
16
|
+
# This is a baker, not a renderer
|
17
|
+
module BakeSASS
|
18
|
+
extend HasCache
|
19
|
+
|
20
|
+
module_function
|
21
|
+
|
22
|
+
SASS_OPTIONS = { cache_store: Sass::CacheStores::Memory.new, style: (ENV['SASS_STYLE'] || ((ENV['ENV'] || ENV['RACK_ENV']) == 'production' ? :compressed : :nested)) }.dup
|
23
|
+
|
24
|
+
# Bakes the SASS for the requested target, if a SASS source file is found.
|
25
|
+
def call(target)
|
26
|
+
return self[target] if File.extname(target) == '.map'.freeze
|
27
|
+
review_cache("#{target}.scss", target) || review_cache("#{target}.sass", target)
|
28
|
+
end
|
29
|
+
|
30
|
+
def review_cache(filename, target)
|
31
|
+
return nil unless File.exist?(filename)
|
32
|
+
eng = self[filename]
|
33
|
+
return true unless eng.nil? || refresh_sass?(filename)
|
34
|
+
self[filename] = (eng = Sass::Engine.for_file(filename, SASS_OPTIONS)).dependencies
|
35
|
+
map_name = "#{target}.map".freeze
|
36
|
+
css, map = eng.render_with_sourcemap(File.basename(map_name))
|
37
|
+
self[filename.to_sym] = Time.now
|
38
|
+
IO.write map_name, map.to_json(css_uri: File.basename(target))
|
39
|
+
self[target] = css
|
40
|
+
end
|
41
|
+
|
42
|
+
def refresh_sass?(sass)
|
43
|
+
mt = self[sass.to_sym]
|
44
|
+
return true if mt < File.mtime(sass)
|
45
|
+
self[sass].each { |e| return true if File.exist?(e.options[:filename]) && (File.mtime(e.options[:filename]) > mt) }
|
46
|
+
false
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
::Plezi::AssetBaker.register :css, ::Plezi::Base::BakeSASS
|
51
|
+
::Plezi::AssetBaker.register :map, ::Plezi::Base::BakeSASS
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'plezi/render/has_cache' unless defined? ::Plezi::Base::HasStore
|
2
|
+
module Plezi
|
3
|
+
module Base
|
4
|
+
module RenderSlim
|
5
|
+
extend ::Plezi::Base::HasStore
|
6
|
+
|
7
|
+
module_function
|
8
|
+
|
9
|
+
def call(filename, context, &block)
|
10
|
+
return unless defined? ::Slim
|
11
|
+
return unless File.exist?(filename)
|
12
|
+
engine = load_engine(filename)
|
13
|
+
engine.render(context.receiver, &block)
|
14
|
+
end
|
15
|
+
if ENV['RACK_ENV'.freeze] == 'production'.freeze
|
16
|
+
def load_engine(filename)
|
17
|
+
engine = self[filename]
|
18
|
+
return engine if engine
|
19
|
+
self[filename] = (Slim::Template.new { ::Plezi.try_utf8!(IO.binread(filename)) })
|
20
|
+
end
|
21
|
+
else
|
22
|
+
def load_engine(filename)
|
23
|
+
engine, tm = self[filename]
|
24
|
+
return engine if engine && (tm == File.mtime(filename))
|
25
|
+
self[filename] = [(engine = Slim::Template.new { ::Plezi.try_utf8!(IO.binread(filename)) }), File.mtime(filename)]
|
26
|
+
engine
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
::Plezi::Renderer.register :slim, ::Plezi::Base::RenderSlim
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'plezi/router/route'
|
2
|
+
require 'plezi/router/errors'
|
3
|
+
require 'plezi/router/assets'
|
4
|
+
require 'rack'
|
5
|
+
|
6
|
+
module Plezi
|
7
|
+
module Base
|
8
|
+
module Router
|
9
|
+
class ADClient
|
10
|
+
def index
|
11
|
+
fname = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'resources', 'client.js'))
|
12
|
+
response.body = File.open(fname)
|
13
|
+
response['X-Sendfile'] = fname
|
14
|
+
true
|
15
|
+
end
|
16
|
+
|
17
|
+
def show
|
18
|
+
index
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'set'
|
3
|
+
module Plezi
|
4
|
+
module Base
|
5
|
+
class Assets
|
6
|
+
if ENV['RACK_ENV'.freeze] == 'production'.freeze
|
7
|
+
def index
|
8
|
+
name = File.join(Plezi.assets, *params['*'.freeze]).freeze
|
9
|
+
data = ::Plezi::AssetBaker.bake(name)
|
10
|
+
return false unless data
|
11
|
+
name = File.join(Iodine::Rack.public, request.path_info[1..-1]).freeze if Iodine::Rack.public
|
12
|
+
if data.is_a?(String)
|
13
|
+
FileUtils.mkpath File.dirname(name)
|
14
|
+
IO.binwrite(name, data)
|
15
|
+
end
|
16
|
+
response['X-Sendfile'.freeze] = name
|
17
|
+
response.body = File.open(name)
|
18
|
+
true
|
19
|
+
end
|
20
|
+
else
|
21
|
+
def index
|
22
|
+
name = File.join(Plezi.assets, *params['*'.freeze]).freeze
|
23
|
+
data = ::Plezi::AssetBaker.bake(name)
|
24
|
+
IO.binwrite(name, data) if data.is_a?(String)
|
25
|
+
if File.exist? name
|
26
|
+
response['X-Sendfile'.freeze] = name
|
27
|
+
response.body = File.open(name)
|
28
|
+
return true
|
29
|
+
end
|
30
|
+
false
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def show
|
35
|
+
index
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
# This module is used for asset "baking" (or "belated baking"). It allows us to easily register and support new types of assets.
|
40
|
+
module AssetBaker
|
41
|
+
@drivers = {}
|
42
|
+
# Registers a new Asset Driver of a specific extension (i.e. "css", "js", etc')
|
43
|
+
#
|
44
|
+
# Multiple Asset Drivers can be registered for the same extension. The will be attempted in the order of their registration.
|
45
|
+
#
|
46
|
+
# An Asset Drivers is an object that responsd to `.call(target)`.
|
47
|
+
# If the traget is newly rendered, the driver should return the rendered text.
|
48
|
+
# If the asset didn't change since the last time `.call(target)` was called, the driver should return 'true' (meanning, yet, the asset exists, it's the same).
|
49
|
+
# If the driver doesn't locate the asset, it should return `nil` or `false`, indicating the next driver should be attempted.
|
50
|
+
def self.register(ext, driver)
|
51
|
+
(@drivers[".#{ext}".freeze] ||= [].to_set) << driver
|
52
|
+
end
|
53
|
+
|
54
|
+
# @private
|
55
|
+
# called by Plezi when in need of baking an asset.
|
56
|
+
def self.bake(name)
|
57
|
+
ret = nil
|
58
|
+
ext = File.extname name
|
59
|
+
return false if ext.empty?
|
60
|
+
driver = @drivers[ext]
|
61
|
+
return false if driver.nil?
|
62
|
+
driver.each { |d| ret = d.call(name); return ret if ret }
|
63
|
+
nil
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
require 'plezi/render/sass.rb'
|