manatee 0.0.1.pre1
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 +7 -0
- data/Gemfile +23 -0
- data/LICENSE.txt +22 -0
- data/README.mdown +55 -0
- data/Rakefile +7 -0
- data/app/assets/javascripts/manatee.js +1 -0
- data/app/assets/javascripts/manatee/helpers.js +4 -0
- data/app/assets/javascripts/manatee/helpers/asset_tag.jsh.coffee +138 -0
- data/app/assets/javascripts/manatee/helpers/asset_url.jsh.coffee +90 -0
- data/app/assets/javascripts/manatee/helpers/csrf.jsh.coffee +5 -0
- data/app/assets/javascripts/manatee/helpers/date.jsh.coffee +54 -0
- data/app/assets/javascripts/manatee/helpers/debug.jsh.coffee +2 -0
- data/app/assets/javascripts/manatee/helpers/form.jsh.coffee +25 -0
- data/app/assets/javascripts/manatee/helpers/form_builder.jsh.coffee +24 -0
- data/app/assets/javascripts/manatee/helpers/form_options.jsh.coffee +267 -0
- data/app/assets/javascripts/manatee/helpers/form_tag.jsh.coffee +204 -0
- data/app/assets/javascripts/manatee/helpers/javascript.jsh.coffee +15 -0
- data/app/assets/javascripts/manatee/helpers/number.jsh.coffee +58 -0
- data/app/assets/javascripts/manatee/helpers/sanitize.jsh.coffee +5 -0
- data/app/assets/javascripts/manatee/helpers/tag.jsh.coffee +58 -0
- data/app/assets/javascripts/manatee/helpers/text.jsh.coffee +12 -0
- data/app/assets/javascripts/manatee/helpers/translation.jsh.coffee +7 -0
- data/app/assets/javascripts/manatee/helpers/url.jsh.coffee +36 -0
- data/app/assets/javascripts/manatee/helpers/util.jsh.coffee +41 -0
- data/app/assets/javascripts/manatee/rails_helpers.js +2 -0
- data/app/assets/javascripts/manatee/rails_helpers/routes.js.erb +195 -0
- data/app/assets/javascripts/manatee/rails_routes.js +1 -0
- data/app/assets/javascripts/manatee/renderer.js.erb +53 -0
- data/app/assets/javascripts/manatee_railsless.js +1 -0
- data/lib/manatee.rb +87 -0
- data/lib/manatee/config.rb +51 -0
- data/lib/manatee/handler.rb +45 -0
- data/lib/manatee/rails.rb +6 -0
- data/lib/manatee/rails/extensions.rb +23 -0
- data/lib/manatee/rails/handler.rb +16 -0
- data/lib/manatee/rails/hash_visitor.rb +35 -0
- data/lib/manatee/rails/helper.rb +9 -0
- data/lib/manatee/rails/resolver.rb +70 -0
- data/lib/manatee/rails/routes_compiler.rb +34 -0
- data/lib/manatee/sprockets.rb +8 -0
- data/lib/manatee/sprockets/jsh_processor_2x.rb +32 -0
- data/lib/manatee/sprockets/jsh_processor_3x.rb +31 -0
- data/lib/manatee/version.rb +3 -0
- data/manatee.gemspec +32 -0
- data/test/example/renderer.js.erb +8 -0
- data/test/example/translations.en.yml +410 -0
- data/test/example/views/index.jst.eco +12 -0
- data/test/helpers/asset_tag_test.rb +175 -0
- data/test/helpers/asset_url_test.rb +349 -0
- data/test/helpers/form_options_test.rb +718 -0
- data/test/helpers/form_tag_test.rb +387 -0
- data/test/helpers/javascript_test.rb +39 -0
- data/test/helpers/number_test.rb +111 -0
- data/test/helpers/tag_test.rb +71 -0
- data/test/support/dom_assertion.rb +49 -0
- data/test/support/view_test.rb +91 -0
- data/test/test_helper.rb +17 -0
- metadata +213 -0
@@ -0,0 +1,53 @@
|
|
1
|
+
I18n.defaultLocale = <%= Manatee.default_locale.to_s.inspect %>;
|
2
|
+
I18n.locale = <%= Manatee.locale.to_s.inspect %>;
|
3
|
+
|
4
|
+
var <%= Manatee.template_namespace %> = <%= Manatee.template_namespace %> || {};
|
5
|
+
var <%= Manatee.renderer_namespace %> = {};
|
6
|
+
|
7
|
+
(function(){
|
8
|
+
function _pushStack(view_name, params){
|
9
|
+
var old_params = {};
|
10
|
+
for(key in params){
|
11
|
+
old_params[key] = this[key];
|
12
|
+
this[key] = params[key];
|
13
|
+
}
|
14
|
+
this._rendering_stack.push( [view_name, old_params] );
|
15
|
+
}
|
16
|
+
|
17
|
+
function _popStack(){
|
18
|
+
var stack = this._rendering_stack.pop();
|
19
|
+
for(key in stack[1]){
|
20
|
+
this[key] = stack[1][key];
|
21
|
+
}
|
22
|
+
}
|
23
|
+
|
24
|
+
function render(view_name, params){
|
25
|
+
params = params || {};
|
26
|
+
_pushStack.call(this, view_name, params);
|
27
|
+
var result = this._templates[view_name].call(this, this);
|
28
|
+
_popStack.call(this);
|
29
|
+
return result;
|
30
|
+
}
|
31
|
+
|
32
|
+
function helper(name, block){
|
33
|
+
this[name] = block.bind(this);
|
34
|
+
}
|
35
|
+
|
36
|
+
function alias(name, aliased_name){
|
37
|
+
this[name] = this[aliased_name];
|
38
|
+
}
|
39
|
+
|
40
|
+
function cleanStack(){
|
41
|
+
this._rendering_stack = [];
|
42
|
+
}
|
43
|
+
|
44
|
+
this.alias = alias.bind(this);
|
45
|
+
this.helper = helper.bind(this);
|
46
|
+
this._templates = <%= Manatee.template_namespace %>;
|
47
|
+
this._context = <%= Manatee.context.to_json %>;
|
48
|
+
this._rendering_stack = [];
|
49
|
+
|
50
|
+
this.helper('render', render);
|
51
|
+
this.helper('cleanStack', cleanStack);
|
52
|
+
|
53
|
+
}).call(<%= Manatee.renderer_namespace %>);
|
@@ -0,0 +1 @@
|
|
1
|
+
//= require ./manatee/helpers
|
data/lib/manatee.rb
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
lib = File.expand_path '..', __FILE__
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
|
4
|
+
require 'json'
|
5
|
+
require 'execjs'
|
6
|
+
require 'i18n-js'
|
7
|
+
require 'sprockets'
|
8
|
+
|
9
|
+
require 'manatee/version'
|
10
|
+
|
11
|
+
require 'manatee/config'
|
12
|
+
require 'manatee/handler'
|
13
|
+
require 'manatee/sprockets'
|
14
|
+
|
15
|
+
if defined? Rails
|
16
|
+
require 'manatee/rails'
|
17
|
+
end
|
18
|
+
|
19
|
+
module Manatee
|
20
|
+
def self.default_config(name, value = nil)
|
21
|
+
define_singleton_method(name) do
|
22
|
+
variable = :"@#{name}"
|
23
|
+
if instance_variable_defined? variable
|
24
|
+
instance_variable_get variable
|
25
|
+
else
|
26
|
+
if block_given?
|
27
|
+
instance_variable_set variable, yield(self)
|
28
|
+
else
|
29
|
+
instance_variable_set variable, value
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
default_config :request_forgery_protection_token, :authenticity_token
|
36
|
+
default_config :protect_from_forgery, true
|
37
|
+
|
38
|
+
default_config :router_namespace, 'RR'
|
39
|
+
default_config :renderer_namespace, 'Renderer'
|
40
|
+
default_config :template_namespace, 'JST'
|
41
|
+
|
42
|
+
default_config :views_asset, 'views'
|
43
|
+
default_config :full_domain, 'http://localhost:3000'
|
44
|
+
|
45
|
+
default_config(:locale){ |c| I18n.locale }
|
46
|
+
default_config(:default_locale){ |c| I18n.default_locale }
|
47
|
+
|
48
|
+
default_config :force_domain, false
|
49
|
+
default_config :force_assets_domain, false
|
50
|
+
|
51
|
+
default_config :default_format, javascript: :js, stylesheet: :css
|
52
|
+
|
53
|
+
default_config :assets_domain, 'http://localhost:3000'
|
54
|
+
|
55
|
+
default_config(:fonts_domain){ |c| c.assets_domain }
|
56
|
+
default_config(:audios_domain){ |c| c.assets_domain }
|
57
|
+
default_config(:videos_domain){ |c| c.assets_domain }
|
58
|
+
default_config(:images_domain){ |c| c.assets_domain }
|
59
|
+
default_config(:javascript_domain){ |c| c.assets_domain }
|
60
|
+
default_config(:stylesheet_domain){ |c| c.assets_domain }
|
61
|
+
|
62
|
+
default_config :assets_path, '/assets'
|
63
|
+
|
64
|
+
default_config(:fonts_path){ |c| c.assets_path + '/fonts' }
|
65
|
+
default_config(:audios_path){ |c| c.assets_path + '/audios' }
|
66
|
+
default_config(:videos_path){ |c| c.assets_path + '/videos' }
|
67
|
+
default_config(:images_path){ |c| c.assets_path + '/images' }
|
68
|
+
default_config(:javascript_path){ |c| c.assets_path + '/javascripts' }
|
69
|
+
default_config(:stylesheet_path){ |c| c.assets_path + '/stylesheets' }
|
70
|
+
|
71
|
+
def self.assets
|
72
|
+
if defined? Rails
|
73
|
+
::Rails.application.assets
|
74
|
+
else
|
75
|
+
@assets or raise("Manatee's Sprockets environment is not configured, call: Manatee.config{ |c| c.assets = sprockets_environment }")
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def self.config(&block)
|
80
|
+
yield Manatee::Config.new
|
81
|
+
end
|
82
|
+
|
83
|
+
def self.context
|
84
|
+
Manatee::Config.context
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Manatee
|
2
|
+
class Config
|
3
|
+
def self.context
|
4
|
+
domain = {
|
5
|
+
app: Manatee.full_domain,
|
6
|
+
asset: Manatee.assets_domain,
|
7
|
+
font: Manatee.fonts_domain,
|
8
|
+
audio: Manatee.audios_domain,
|
9
|
+
video: Manatee.videos_domain,
|
10
|
+
image: Manatee.images_domain,
|
11
|
+
javascript: Manatee.javascript_domain,
|
12
|
+
stylesheet: Manatee.stylesheet_domain
|
13
|
+
}
|
14
|
+
|
15
|
+
default_path = {
|
16
|
+
asset: Manatee.assets_path,
|
17
|
+
font: Manatee.fonts_path,
|
18
|
+
audio: Manatee.audios_path,
|
19
|
+
video: Manatee.videos_path,
|
20
|
+
image: Manatee.images_path,
|
21
|
+
javascript: Manatee.javascript_path,
|
22
|
+
stylesheet: Manatee.stylesheet_path
|
23
|
+
}
|
24
|
+
|
25
|
+
force_asset_domain = Manatee.force_assets_domain || Manatee.full_domain != Manatee.assets_domain
|
26
|
+
|
27
|
+
{
|
28
|
+
domain: domain,
|
29
|
+
forceDomain: Manatee.force_domain,
|
30
|
+
defaultPath: default_path,
|
31
|
+
defaultFormat: Manatee.default_format,
|
32
|
+
forceAssetDomain: force_asset_domain,
|
33
|
+
protectFromForgery: Manatee.protect_from_forgery,
|
34
|
+
requestForgeryProtectionToken: Manatee.request_forgery_protection_token
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
def method_missing(method, *args, &block)
|
39
|
+
str_method = method.to_s
|
40
|
+
if str_method[-1] == '=' && Manatee.methods(false).include?(str_method[0..-2].to_sym)
|
41
|
+
if block_given?
|
42
|
+
Manatee.default_config str_method[0..-2].to_sym, &block
|
43
|
+
else
|
44
|
+
Manatee.instance_variable_set :"@#{str_method[0..-2]}", args.first
|
45
|
+
end
|
46
|
+
else
|
47
|
+
super method, *args, &block
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
|
3
|
+
module Manatee
|
4
|
+
class Handler
|
5
|
+
include Singleton
|
6
|
+
|
7
|
+
def eval_template(identifier, params = {})
|
8
|
+
context.call javascript_template_code(identifier, params), params
|
9
|
+
end
|
10
|
+
|
11
|
+
def eval(javascript_code)
|
12
|
+
context.eval javascript_code
|
13
|
+
end
|
14
|
+
|
15
|
+
def context
|
16
|
+
check_context
|
17
|
+
@context
|
18
|
+
end
|
19
|
+
|
20
|
+
def reset!
|
21
|
+
@context = nil
|
22
|
+
end
|
23
|
+
|
24
|
+
protected
|
25
|
+
def javascript_template_code(identifier, params)
|
26
|
+
token = params[:csrf_token] ? params[:csrf_token].inspect : false
|
27
|
+
"(function(){ this.csrfToken = #{token}; return #{Manatee.template_namespace}[#{ identifier.inspect }]; }).call(#{Manatee.renderer_namespace})"
|
28
|
+
end
|
29
|
+
|
30
|
+
def check_context
|
31
|
+
load_context if !instance_variable_get(:@context) || @last_mtime != views_asset.mtime
|
32
|
+
end
|
33
|
+
|
34
|
+
def load_context
|
35
|
+
asset = views_asset
|
36
|
+
@last_mtime = asset.mtime
|
37
|
+
@context = ExecJS.compile asset.source
|
38
|
+
end
|
39
|
+
|
40
|
+
def views_asset
|
41
|
+
Manatee.assets[ Manatee.views_asset ]
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module ActionDispatch::Journey
|
2
|
+
module Nodes
|
3
|
+
class Node
|
4
|
+
def compile_hash
|
5
|
+
Manatee::Rails::HashVisitor.new.accept self
|
6
|
+
end
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
# This is required to Rails for using app directory
|
12
|
+
module Manatee
|
13
|
+
class Engine < ::Rails::Engine
|
14
|
+
end
|
15
|
+
|
16
|
+
# This method must be used to hook Manatee into Rails
|
17
|
+
def self.subscribe_on_rails
|
18
|
+
ActionView::Base.send :include, Manatee::Rails::Helper
|
19
|
+
ApplicationController.prepend_view_path Manatee::Rails::Resolver.new(Manatee.views_asset)
|
20
|
+
ActionView::Template.register_template_handler :'jst', Manatee::Rails::Handler.instance
|
21
|
+
Manatee::Sprockets::JshProcessor.subscribe ::Rails.application.assets
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Manatee
|
2
|
+
module Rails
|
3
|
+
class Handler < Manatee::Handler
|
4
|
+
|
5
|
+
def self.default_format
|
6
|
+
Mime::HTML
|
7
|
+
end
|
8
|
+
|
9
|
+
def call(template)
|
10
|
+
identifier = template.identifier
|
11
|
+
"Manatee::Handler.instance.eval_template #{ identifier.inspect }, self.assigns.except('marked_for_same_origin_verification').merge(csrf_token: form_authenticity_token)"
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Manatee
|
2
|
+
module Rails
|
3
|
+
class HashVisitor < ActionDispatch::Journey::Visitors::Visitor
|
4
|
+
|
5
|
+
private
|
6
|
+
def visit_GROUP(node)
|
7
|
+
{
|
8
|
+
type: node.type,
|
9
|
+
children: [ visit(node.left) ]
|
10
|
+
}
|
11
|
+
end
|
12
|
+
|
13
|
+
def terminal(node)
|
14
|
+
{
|
15
|
+
type: node.type,
|
16
|
+
value: node.left.to_s
|
17
|
+
}
|
18
|
+
end
|
19
|
+
|
20
|
+
def binary(node)
|
21
|
+
{
|
22
|
+
type: node.type,
|
23
|
+
children:[ visit(node.left), visit(node.right) ]
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
def nary(node)
|
28
|
+
{
|
29
|
+
type: node.type,
|
30
|
+
children: node.children.map{ |c| visit c }
|
31
|
+
}
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module Manatee
|
2
|
+
module Rails
|
3
|
+
class Resolver < ActionView::Resolver
|
4
|
+
|
5
|
+
def initialize(jst_template_path)
|
6
|
+
super()
|
7
|
+
@jst_template_path = jst_template_path
|
8
|
+
end
|
9
|
+
|
10
|
+
protected
|
11
|
+
def find_templates(name, prefix, partial, details)
|
12
|
+
if details[:handlers].include? :jst
|
13
|
+
path = normalize_path prefix, name, partial
|
14
|
+
locales = normalize_array details[:locale]
|
15
|
+
formats = normalize_array details[:formats]
|
16
|
+
|
17
|
+
templates = []
|
18
|
+
formats.each do |format|
|
19
|
+
locales.each do |locale|
|
20
|
+
template = find_asset_template path, locale, format
|
21
|
+
templates << template if template
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
templates
|
26
|
+
else
|
27
|
+
[]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def find_asset_template(path, locale, format)
|
32
|
+
identifier = [normalize_identifier(path), locale, format].compact.join '.'
|
33
|
+
build_template Manatee.assets["#{identifier}.jst"], path, identifier, format
|
34
|
+
end
|
35
|
+
|
36
|
+
def normalize_path(prefix, name, partial)
|
37
|
+
name = partial ? "_#{name}" : name
|
38
|
+
prefix.present? ? "#{prefix}/#{name}" : name
|
39
|
+
end
|
40
|
+
|
41
|
+
def normalize_identifier(path)
|
42
|
+
"#{@jst_template_path}/#{path}"
|
43
|
+
end
|
44
|
+
|
45
|
+
def normalize_array(array)
|
46
|
+
return [nil] if array.blank?
|
47
|
+
normalized_array = array.map(&:to_s).uniq.compact
|
48
|
+
normalized_array << nil
|
49
|
+
end
|
50
|
+
|
51
|
+
def build_template(asset, path, identifier, format)
|
52
|
+
return nil unless asset
|
53
|
+
|
54
|
+
source = asset.source
|
55
|
+
identifier = identifier
|
56
|
+
handler = ActionView::Template.registered_template_handler :jst
|
57
|
+
|
58
|
+
format = format ? Mime[format] : Mime::HTML
|
59
|
+
details = {
|
60
|
+
format: format,
|
61
|
+
updated_at: asset.mtime,
|
62
|
+
virtual_path: path
|
63
|
+
}
|
64
|
+
|
65
|
+
ActionView::Template.new source, identifier, handler, details
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Manatee
|
2
|
+
module Rails
|
3
|
+
class RoutesCompiler
|
4
|
+
def compile
|
5
|
+
named_routes.map do |name|
|
6
|
+
compile_route name, named_routes[name].path
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
protected
|
11
|
+
def compile_route(name, path)
|
12
|
+
{
|
13
|
+
name: name.to_s,
|
14
|
+
helper_name: helper_name(name),
|
15
|
+
names: path.names,
|
16
|
+
optional_names: path.optional_names,
|
17
|
+
required_names: path.required_names,
|
18
|
+
ast: path.spec.compile_hash
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
def helper_name(name)
|
23
|
+
helper_name = name.to_s.camelize
|
24
|
+
helper_name[0] = helper_name[0].downcase
|
25
|
+
helper_name
|
26
|
+
end
|
27
|
+
|
28
|
+
def named_routes
|
29
|
+
::Rails.application.routes.named_routes
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|