plezi 0.12.22 → 0.14.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 +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'
|