plezi 0.14.4 → 0.14.5
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 +12 -0
- data/bin/ws_shootout +30 -0
- data/exe/plezi +108 -108
- data/lib/plezi.rb +18 -26
- data/lib/plezi/activation.rb +16 -16
- data/lib/plezi/api.rb +51 -50
- data/lib/plezi/controller/controller.rb +249 -229
- data/lib/plezi/controller/controller_class.rb +189 -174
- data/lib/plezi/controller/cookies.rb +49 -47
- data/lib/plezi/helpers.rb +35 -35
- data/lib/plezi/render/erb.rb +25 -26
- data/lib/plezi/render/has_cache.rb +31 -31
- data/lib/plezi/render/markdown.rb +53 -53
- data/lib/plezi/render/render.rb +36 -38
- data/lib/plezi/render/sass.rb +43 -44
- data/lib/plezi/render/slim.rb +25 -25
- data/lib/plezi/router/adclient.rb +14 -15
- data/lib/plezi/router/assets.rb +59 -61
- data/lib/plezi/router/errors.rb +22 -22
- data/lib/plezi/router/route.rb +98 -100
- data/lib/plezi/router/router.rb +120 -113
- data/lib/plezi/version.rb +1 -1
- data/lib/plezi/websockets/message_dispatch.rb +118 -80
- data/lib/plezi/websockets/redis.rb +42 -43
- data/plezi.gemspec +3 -3
- data/resources/client.js +229 -204
- data/resources/ctrlr.rb +26 -26
- data/resources/mini_app.rb +1 -1
- data/resources/simple-client.js +50 -43
- metadata +9 -8
data/lib/plezi/helpers.rb
CHANGED
@@ -2,13 +2,13 @@ require 'plezi/activation'
|
|
2
2
|
require 'plezi/router/router'
|
3
3
|
|
4
4
|
module Plezi
|
5
|
-
|
5
|
+
module_function
|
6
6
|
|
7
7
|
# attempts to convert a string's encoding to UTF-8, but only when the string is a valid UTF-8 encoded string.
|
8
8
|
def try_utf8!(string, encoding = ::Encoding::UTF_8)
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
return nil unless string
|
10
|
+
string.force_encoding(::Encoding::ASCII_8BIT) unless string.force_encoding(encoding).valid_encoding?
|
11
|
+
string
|
12
12
|
end
|
13
13
|
|
14
14
|
# Sanitizes hash data, attempting to "rubyfy" any Hash Strings to reversible Ruby objects. i.e:
|
@@ -21,40 +21,40 @@ module Plezi
|
|
21
21
|
#
|
22
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
23
|
def rubyfy(hash)
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
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
45
|
end
|
46
46
|
|
47
47
|
# Catches String/Symbol mixups. Add this to any Hash using Hash#default_proc=
|
48
48
|
def hash_proc_4symstr
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
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
59
|
end
|
60
60
|
end
|
data/lib/plezi/render/erb.rb
CHANGED
@@ -1,34 +1,33 @@
|
|
1
1
|
require 'plezi/render/has_cache' unless defined? ::Plezi::Base::HasStore
|
2
|
-
require 'erb'
|
3
2
|
module Plezi
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
module Base
|
4
|
+
module RenderERB
|
5
|
+
extend ::Plezi::Base::HasStore
|
7
6
|
|
8
|
-
|
7
|
+
module_function
|
9
8
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
9
|
+
def call(filename, context, &block)
|
10
|
+
return unless defined? ::ERB
|
11
|
+
return unless File.exist?(filename)
|
12
|
+
engine = load_engine(filename)
|
13
|
+
engine.result(context, &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] = ::ERB.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 = ::ERB.new(::Plezi.try_utf8!(IO.binread(filename)))), File.mtime(filename)]
|
26
|
+
engine
|
27
|
+
end
|
28
|
+
end
|
15
29
|
end
|
16
|
-
|
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
|
30
|
+
end
|
32
31
|
end
|
33
32
|
|
34
33
|
::Plezi::Renderer.register :erb, ::Plezi::Base::RenderERB
|
@@ -1,36 +1,36 @@
|
|
1
1
|
module Plezi
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
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
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
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
|
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
|
27
21
|
end
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
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
|
32
34
|
end
|
33
|
-
|
34
|
-
end
|
35
|
-
end
|
35
|
+
end
|
36
36
|
end
|
@@ -1,63 +1,63 @@
|
|
1
1
|
require 'plezi/render/has_cache' unless defined? ::Plezi::Base::HasStore
|
2
2
|
# Redcarpet might not be available, if so, allow the require to throw it's exception.
|
3
3
|
unless defined?(::Redcarpet::Markdown)
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
begin
|
5
|
+
require('redcarpet')
|
6
|
+
rescue Exception
|
7
7
|
|
8
|
-
|
8
|
+
end
|
9
9
|
end
|
10
10
|
|
11
11
|
if defined?(Redcarpet::Markdown)
|
12
|
-
|
13
|
-
|
14
|
-
|
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
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
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
|
58
59
|
end
|
59
|
-
|
60
|
-
end
|
60
|
+
end
|
61
61
|
|
62
|
-
|
62
|
+
::Plezi::Renderer.register :md, ::Plezi::Base::RenderMarkDown
|
63
63
|
end
|
data/lib/plezi/render/render.rb
CHANGED
@@ -1,47 +1,45 @@
|
|
1
|
-
require 'thread'
|
2
|
-
|
3
1
|
module Plezi
|
4
|
-
|
5
|
-
|
2
|
+
module Renderer
|
3
|
+
@render_library = {}.dup
|
6
4
|
|
7
|
-
|
5
|
+
public
|
8
6
|
|
9
|
-
|
7
|
+
module_function
|
10
8
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
9
|
+
# Registers a rendering extention.
|
10
|
+
#
|
11
|
+
# Slim, Markdown, ERB and SASS are registered by default.
|
12
|
+
#
|
13
|
+
# extention:: a Symbol or String representing the extention of the file to be rendered. i.e. 'slim', 'md', 'erb', etc'
|
14
|
+
# handler :: a Proc or other object that answers to call(filename, context, &block) and returnes the rendered string.
|
15
|
+
# The block accepted by the handler is for chaining rendered actions (allowing for `yield` within templates)
|
16
|
+
# and the context is the object within which the rendering should be performed (if `binding` handling is
|
17
|
+
# supported by the engine). `filename` might not point to an existing or valid file.
|
18
|
+
#
|
19
|
+
# If a block is passed to the `register_hook` method with no handler defined, it will act as the handler.
|
20
|
+
def register(extention, handler = nil, &block)
|
21
|
+
handler ||= block
|
22
|
+
raise 'Handler or block required.' unless handler
|
23
|
+
@render_library[extention.to_s] = handler
|
24
|
+
handler
|
25
|
+
end
|
28
26
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
27
|
+
# Removes a registered render extention
|
28
|
+
def remove(extention)
|
29
|
+
@render_library.delete extention.to_s
|
30
|
+
end
|
33
31
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
32
|
+
# Attempts to render the requested file (i.e. `'index.html'`) using all known rendering handlers.
|
33
|
+
def render(base_filename, context = (Object.new.instance_eval { binding }), &block)
|
34
|
+
ret = nil
|
35
|
+
@render_library.each { |ext, handler| ret = handler.call("#{base_filename}.#{ext}".freeze, context, &block); return ret if ret; }
|
36
|
+
ret
|
37
|
+
end
|
38
|
+
# Renderer.register :haml do |filename, context, &block|
|
39
|
+
# next unless defined? ::Haml
|
40
|
+
# (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)
|
41
|
+
# end
|
42
|
+
end
|
45
43
|
end
|
46
44
|
|
47
45
|
require 'plezi/render/slim.rb'
|
data/lib/plezi/render/sass.rb
CHANGED
@@ -1,55 +1,54 @@
|
|
1
|
-
require 'thread'
|
2
1
|
require 'plezi/render/has_cache'
|
3
2
|
# Redcarpet might not be available, if so, allow the require to throw it's exception.
|
4
3
|
unless defined?(::Sass)
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
begin
|
5
|
+
require('sass')
|
6
|
+
rescue Exception
|
8
7
|
|
9
|
-
|
8
|
+
end
|
10
9
|
end
|
11
10
|
|
12
11
|
if defined?(::Sass)
|
13
12
|
|
14
|
-
|
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
|
-
|
13
|
+
module Plezi
|
14
|
+
module Base
|
15
|
+
# This is a baker, not a renderer
|
16
|
+
module BakeSASS
|
17
|
+
extend HasCache
|
18
|
+
|
19
|
+
module_function
|
20
|
+
|
21
|
+
SASS_OPTIONS = { cache_store: Sass::CacheStores::Memory.new, style: (ENV['SASS_STYLE'] || ((ENV['ENV'] || ENV['RACK_ENV']) == 'production' ? :compressed : :nested)) }.dup
|
22
|
+
|
23
|
+
# Bakes the SASS for the requested target, if a SASS source file is found.
|
24
|
+
def call(target)
|
25
|
+
return self[target] if File.extname(target) == '.map'.freeze
|
26
|
+
review_cache("#{target}.scss", target) || review_cache("#{target}.sass", target)
|
27
|
+
end
|
28
|
+
|
29
|
+
def review_cache(filename, target)
|
30
|
+
return nil unless File.exist?(filename)
|
31
|
+
eng = self[filename]
|
32
|
+
return true unless eng.nil? || refresh_sass?(filename)
|
33
|
+
self[filename] = (eng = Sass::Engine.for_file(filename, SASS_OPTIONS)).dependencies
|
34
|
+
map_name = "#{target}.map".freeze
|
35
|
+
css, map = eng.render_with_sourcemap(File.basename(map_name))
|
36
|
+
self[filename.to_sym] = Time.now
|
37
|
+
IO.write map_name, map.to_json(css_uri: File.basename(target))
|
38
|
+
self[target] = css
|
39
|
+
end
|
40
|
+
|
41
|
+
def refresh_sass?(sass)
|
42
|
+
mt = self[sass.to_sym]
|
43
|
+
return true if mt < File.mtime(sass)
|
44
|
+
self[sass].each { |e| return true if File.exist?(e.options[:filename]) && (File.mtime(e.options[:filename]) > mt) }
|
45
|
+
false
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
::Plezi::AssetBaker.register :css, ::Plezi::Base::BakeSASS
|
50
|
+
::Plezi::AssetBaker.register :map, ::Plezi::Base::BakeSASS
|
48
51
|
end
|
49
|
-
|
50
|
-
::Plezi::AssetBaker.register :css, ::Plezi::Base::BakeSASS
|
51
|
-
::Plezi::AssetBaker.register :map, ::Plezi::Base::BakeSASS
|
52
|
-
end
|
53
|
-
end
|
52
|
+
end
|
54
53
|
|
55
54
|
end
|