tight-engine 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/Gemfile +1 -0
- data/lib/tight-engine.rb +23 -0
- data/lib/tight-engine/defer.rb +30 -0
- data/lib/tight-engine/init.rb +120 -0
- data/lib/tight-engine/locale.rb +40 -0
- data/lib/tight-engine/render.rb +193 -0
- data/lib/tight-engine/template.rb +60 -0
- data/lib/tight-engine/url.rb +27 -0
- data/lib/tight-engine/utils.rb +62 -0
- data/lib/tight-engine/version.rb +5 -0
- data/tight-engine.gemspec +2 -2
- metadata +13 -19
- data/lib/tight-auth.rb +0 -10
- data/lib/tight-auth/access.rb +0 -148
- data/lib/tight-auth/login.rb +0 -138
- data/lib/tight-auth/login/controller.rb +0 -20
- data/lib/tight-auth/login/layout.slim +0 -10
- data/lib/tight-auth/login/new.slim +0 -37
- data/lib/tight-auth/permissions.rb +0 -180
- data/lib/tight/version.rb +0 -3
- data/test/auth_helper.rb +0 -83
- data/test/test_padrino_access.rb +0 -124
- data/test/test_padrino_auth.rb +0 -38
- data/test/test_padrino_login.rb +0 -76
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d9af08abd886546c991e706361e0a40872e0e6ca
|
4
|
+
data.tar.gz: b9e8bb833bf96cfbc027ff4f446c41b085930b1c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: da17884b6953ce5babcb31c05a577f114c56f16ae41dde952840a849c0d6f70ea297d92c33025da579b3a491ded507a523d1d810a827cb66b3db962da1280aab
|
7
|
+
data.tar.gz: 1e6484ce7ec08c592a25c9fb9575f853b8826986ca8868883ad3eab2a94d4a95d639bed33d8f7f024ef47573aa8c60b3ff649261ad85cf2120f790457c49d618
|
data/.gitignore
CHANGED
data/Gemfile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
gemspec
|
data/lib/tight-engine.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'tight-engine/init'
|
2
|
+
require 'tight-engine/locale'
|
3
|
+
require 'tight-engine/defer'
|
4
|
+
require 'tight-engine/template'
|
5
|
+
require 'tight-engine/render'
|
6
|
+
require 'tight-engine/url'
|
7
|
+
require 'tight-engine/utils'
|
8
|
+
|
9
|
+
module Tight
|
10
|
+
module Engine
|
11
|
+
def self.registered(app)
|
12
|
+
app.send(:include, Tight::Engine::Init)
|
13
|
+
app.send(:include, Tight::Engine::Locale)
|
14
|
+
app.send(:include, Tight::Engine::Defer)
|
15
|
+
app.send(:include, Tight::Engine::Template)
|
16
|
+
app.send(:include, Tight::Engine::Render)
|
17
|
+
app.send(:include, Tight::Engine::Url)
|
18
|
+
app.send(:include, Tight::Engine::Utils)
|
19
|
+
|
20
|
+
app.default :deferred_elements, []
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Tight
|
2
|
+
module Engine
|
3
|
+
module Defer
|
4
|
+
def placeholders
|
5
|
+
@placeholders ||= {}
|
6
|
+
end
|
7
|
+
|
8
|
+
def defer_element( name, args, opts )
|
9
|
+
return unless settings.deferred_elements.include?(name)
|
10
|
+
placeholders[name] = [ name, args, opts ]
|
11
|
+
"%{placeholder[:#{name}]}"
|
12
|
+
end
|
13
|
+
|
14
|
+
def process_deferred_elements( text )
|
15
|
+
text.to_str.gsub /(\s*)\%\{placeholder\[\:([^\]]+)\]\}/ do
|
16
|
+
if deferred = placeholders[$2]
|
17
|
+
output = process_element *deferred
|
18
|
+
if engine.pretty?
|
19
|
+
$1+output.gsub(/\r|\n|\r\n/, $1)+$1
|
20
|
+
else
|
21
|
+
output
|
22
|
+
end
|
23
|
+
else
|
24
|
+
''
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
|
3
|
+
module Tight
|
4
|
+
module Engine
|
5
|
+
module Init
|
6
|
+
def engine
|
7
|
+
@tight_env ||= OpenStruct.new
|
8
|
+
end
|
9
|
+
|
10
|
+
def init_page
|
11
|
+
path = normalize_path swift.path
|
12
|
+
page = find_page_or_module path
|
13
|
+
redirect_if_blank page
|
14
|
+
merge_default_params page
|
15
|
+
init_path_pages page
|
16
|
+
@page = page
|
17
|
+
end
|
18
|
+
|
19
|
+
def init_error( errno )
|
20
|
+
init_path_pages
|
21
|
+
@page = Page.first :path => "/error/#{errno}"
|
22
|
+
@page ||= Page.new :title => "Error #{errno}", :text => "page /error/#{errno} not found"
|
23
|
+
end
|
24
|
+
|
25
|
+
def init_swift
|
26
|
+
return if @_inited
|
27
|
+
init_folders
|
28
|
+
init_media
|
29
|
+
init_locale
|
30
|
+
init_http
|
31
|
+
@_inited = true
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def find_page_or_module( path )
|
37
|
+
page = Page.first( :conditions => [ "? LIKE IF(is_module,CONCAT(path,'%'),path)", path ], :order => :path.desc )
|
38
|
+
detect_module_slug page, path
|
39
|
+
end
|
40
|
+
|
41
|
+
def normalize_path( path )
|
42
|
+
path.squeeze! '/'
|
43
|
+
path[1] ? path.chomp('/') : path
|
44
|
+
end
|
45
|
+
|
46
|
+
def redirect_if_blank( page )
|
47
|
+
if page && page.parent_id && page.fragment_id == 'page' && page.text.blank? && !page.is_module
|
48
|
+
first_child = page.children.first( :order => :position )
|
49
|
+
redirect first_child.path if first_child
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def merge_default_params( page )
|
54
|
+
params.reverse_merge! Rack::Utils.parse_query(page.params) if page && page.params.present?
|
55
|
+
end
|
56
|
+
|
57
|
+
def detect_module_slug( page, path )
|
58
|
+
if page && page.is_module
|
59
|
+
swift.module_root = page.path
|
60
|
+
swift.slug = case path[page.path.length]
|
61
|
+
when '/'
|
62
|
+
path[(page.path.length+1)..-1]
|
63
|
+
when nil
|
64
|
+
''
|
65
|
+
else
|
66
|
+
page = nil
|
67
|
+
end
|
68
|
+
end
|
69
|
+
page
|
70
|
+
end
|
71
|
+
|
72
|
+
def init_path_pages( page = Page.root )
|
73
|
+
while page
|
74
|
+
swift.path_pages.unshift page
|
75
|
+
swift.path_ids.unshift page.id
|
76
|
+
page = page.parent
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def init_http
|
81
|
+
swift.http_method = request.env['REQUEST_METHOD']
|
82
|
+
swift.host = request.env['SERVER_NAME']
|
83
|
+
swift.request = request.env['REQUEST_URI']
|
84
|
+
swift.uri = "/#{params[:request_uri]}"
|
85
|
+
swift.path = swift.uri.partition('?').first
|
86
|
+
swift.path_pages = []
|
87
|
+
swift.path_ids = []
|
88
|
+
end
|
89
|
+
|
90
|
+
def init_folders
|
91
|
+
swift.root = Swift::Application.root
|
92
|
+
swift.public = Swift::Application.public_folder
|
93
|
+
swift.views = Swift::Application.views
|
94
|
+
end
|
95
|
+
|
96
|
+
def init_media
|
97
|
+
media = params.has_key?('print') ? 'print' : 'screen'
|
98
|
+
swift.send("#{media}?=", media)
|
99
|
+
swift.media = media
|
100
|
+
swift.send("pretty?=", Padrino.env == :development)
|
101
|
+
end
|
102
|
+
|
103
|
+
def init_locale
|
104
|
+
swift.locales = Option(:locales) || %w(ru en)
|
105
|
+
swift.locale = params[:locale] ? detect_selected_locale : detect_session_locale
|
106
|
+
session[:locale] = swift.locale
|
107
|
+
I18n.available_locales = swift.locales
|
108
|
+
I18n.locale = swift.locale
|
109
|
+
end
|
110
|
+
|
111
|
+
public
|
112
|
+
|
113
|
+
# deprecated
|
114
|
+
def swift
|
115
|
+
warn '#swift method is deprecated'
|
116
|
+
@tight_env ||= OpenStruct.new
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Tight
|
2
|
+
module Engine
|
3
|
+
module Locale
|
4
|
+
private
|
5
|
+
|
6
|
+
def detect_selected_locale
|
7
|
+
selected_locale = params[:locale].to_s[0..1]
|
8
|
+
if swift.locales.include?(selected_locale)
|
9
|
+
selected_locale.to_sym
|
10
|
+
else
|
11
|
+
detect_session_locale
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def detect_session_locale
|
16
|
+
if session[:locale].present? && swift.locales.include?(session[:locale].to_s)
|
17
|
+
session[:locale].to_sym
|
18
|
+
else
|
19
|
+
detect_preferred_locale
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def detect_preferred_locale
|
24
|
+
detected_locale = if preferred_languages = request.env['HTTP_ACCEPT_LANGUAGE']
|
25
|
+
(parse_http_accept_language(preferred_languages) & swift.locales).first
|
26
|
+
end
|
27
|
+
detected_locale ||= swift.locales.first
|
28
|
+
detected_locale.to_sym
|
29
|
+
end
|
30
|
+
|
31
|
+
def parse_http_accept_language( languages )
|
32
|
+
languages.gsub(/\s+/,'').split(/,/)
|
33
|
+
.sort_by{ |tags| -(tags.partition(/;/).last.split(/=/)[1]||1).to_f }
|
34
|
+
.map{ |language| language[0..1] }.uniq
|
35
|
+
rescue # !!! FIXME detect valid Exceptions
|
36
|
+
[]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,193 @@
|
|
1
|
+
module Tight
|
2
|
+
module Engine
|
3
|
+
module Render
|
4
|
+
MAX_PARSE_LEVEL = 4
|
5
|
+
|
6
|
+
REGEX_RECURSIVE_BRACKETS = /
|
7
|
+
(?<re> #
|
8
|
+
\[ #
|
9
|
+
(?: #
|
10
|
+
(?>[^\[\]]+) # 1
|
11
|
+
| #
|
12
|
+
\g<re> #
|
13
|
+
)* #
|
14
|
+
\] #
|
15
|
+
) #
|
16
|
+
/x.freeze
|
17
|
+
|
18
|
+
def strip_code( text )
|
19
|
+
text && text.gsub(REGEX_RECURSIVE_BRACKETS, '').strip
|
20
|
+
end
|
21
|
+
|
22
|
+
def engine_render( text )
|
23
|
+
Markdown.render( parse_content( text.to_s ) ).html_safe
|
24
|
+
end
|
25
|
+
|
26
|
+
def inline_render( text )
|
27
|
+
engine_render( text ).gsub(/^<p>(.*)<\/p>$/, '\1').chomp
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def parse_content( text )
|
33
|
+
limit_recursion do |flags|
|
34
|
+
draft = text.gsub(REGEX_RECURSIVE_BRACKETS) do |tag|
|
35
|
+
internal_tag(tag) || external_tag(tag, flags)
|
36
|
+
end
|
37
|
+
capture_tag_content draft, flags
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
INTERNAL_TAGS = {
|
42
|
+
'page' => 'PageLink',
|
43
|
+
'link' => 'PageLink',
|
44
|
+
'block' => 'Block',
|
45
|
+
'table' => 'Block',
|
46
|
+
'image' => 'Image',
|
47
|
+
'img' => 'Image',
|
48
|
+
'file' => 'File',
|
49
|
+
'asset' => 'File',
|
50
|
+
'element' => :self,
|
51
|
+
}.freeze
|
52
|
+
|
53
|
+
def dispatch_element( tag_name, args, opts )
|
54
|
+
element_name = INTERNAL_TAGS[tag_name] or return
|
55
|
+
element_name = args.shift if element_name == :self
|
56
|
+
process_element element_name, args, opts
|
57
|
+
end
|
58
|
+
|
59
|
+
REGEX_INTERNAL_TAG = /
|
60
|
+
\[ # [
|
61
|
+
(#{INTERNAL_TAGS.keys.join('|')}) # 1, -- tag name
|
62
|
+
( # 2, -- identity
|
63
|
+
(?:[\:\.\#][\w\-]*)* #
|
64
|
+
) #
|
65
|
+
\s+ #
|
66
|
+
(.*) # 3, -- arguments
|
67
|
+
\] # ]
|
68
|
+
/x.freeze
|
69
|
+
|
70
|
+
def internal_tag( tag )
|
71
|
+
data = tag.match(REGEX_INTERNAL_TAG) or return
|
72
|
+
tag_name, identity, vars = data[1..-1]
|
73
|
+
args, opts = parse_vars vars
|
74
|
+
opts[:title] = detect_title( tag_name, args ) if opts[:title].blank?
|
75
|
+
detect_identity identity, opts
|
76
|
+
dispatch_element tag_name, args, opts
|
77
|
+
end
|
78
|
+
|
79
|
+
def external_tag( tag, flags )
|
80
|
+
tag_name, _, vars = tag[1..-2].partition ' '
|
81
|
+
code = Code.first( :slug => tag_name ) unless tag_name[0] == '/'
|
82
|
+
if code && code.is_single
|
83
|
+
args, opts = parse_vars vars
|
84
|
+
parse_code( code.html, args )
|
85
|
+
else
|
86
|
+
flags[:needs_capturing] = true if code
|
87
|
+
tag
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
REGEX_IDENTITY = /
|
92
|
+
[\:\.\#] # prefix :.#
|
93
|
+
[\w\-]* # identity name
|
94
|
+
/x.freeze
|
95
|
+
|
96
|
+
def detect_identity( identity, opts )
|
97
|
+
identity.to_s.scan(REGEX_IDENTITY).each do |attr|
|
98
|
+
prefix, name = attr[0], attr[1..-1]
|
99
|
+
case prefix
|
100
|
+
when '#'
|
101
|
+
opts[:id] ||= name
|
102
|
+
when '.'
|
103
|
+
if opts[:class].blank?
|
104
|
+
opts[:class] = name
|
105
|
+
else
|
106
|
+
opts[:class] << ' ' << name
|
107
|
+
end
|
108
|
+
when ':'
|
109
|
+
opts[:instance] = name
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def detect_title( type, args )
|
115
|
+
newtitle = if type == 'element'
|
116
|
+
args[2..-1]||[]
|
117
|
+
else
|
118
|
+
args[1..-1]||[]
|
119
|
+
end.join(' ').strip
|
120
|
+
parse_content(newtitle) if newtitle.present?
|
121
|
+
end
|
122
|
+
|
123
|
+
def capture_tag_content( str, flags )
|
124
|
+
return str unless flags[:needs_capturing]
|
125
|
+
str.gsub( /\[([^\s]*)\s*(.*?)\](.*?)\[\/(\1)\]/m ) do |s|
|
126
|
+
args, _ = parse_vars $2
|
127
|
+
code = Code.by_slug $1 #!!! FIXME database call
|
128
|
+
parse_code code.html, args, $3
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def limit_recursion
|
133
|
+
@parse_level ||= 0
|
134
|
+
@parse_level += 1
|
135
|
+
raise SystemStackError, 'parse level too deep' if @parse_level > MAX_PARSE_LEVEL
|
136
|
+
result = yield({})
|
137
|
+
@parse_level -= 1
|
138
|
+
result
|
139
|
+
end
|
140
|
+
|
141
|
+
REGEX_VARS = /
|
142
|
+
( # 0
|
143
|
+
([\S^,]+)\:\s* # 1
|
144
|
+
(?: #
|
145
|
+
["']([^"']+)["'] | # 2
|
146
|
+
([^,'"\s]+) # 3 "'
|
147
|
+
) #
|
148
|
+
),? | #
|
149
|
+
( # 4
|
150
|
+
([^'"\s]+) | # 5 "'
|
151
|
+
["']([^"']+)["'],? # 6
|
152
|
+
)
|
153
|
+
/x.freeze
|
154
|
+
|
155
|
+
def parse_vars( vars )
|
156
|
+
args = []
|
157
|
+
opts = {}
|
158
|
+
vars.scan(REGEX_VARS).each do |v|
|
159
|
+
opts[v[1].to_sym] = ( v[2] || v[3] ) if v[0]
|
160
|
+
args << ( v[5] || v[6] ) if v[4]
|
161
|
+
end
|
162
|
+
[args, opts]
|
163
|
+
end
|
164
|
+
|
165
|
+
REGEX_EXTERNAL_TAG = /
|
166
|
+
\[ #
|
167
|
+
(\d+) # 1
|
168
|
+
(?: #
|
169
|
+
\: #
|
170
|
+
(.*?) # 2
|
171
|
+
)? #
|
172
|
+
\] #
|
173
|
+
| #
|
174
|
+
\[ #
|
175
|
+
(content) # 3
|
176
|
+
\] #
|
177
|
+
/x.freeze
|
178
|
+
|
179
|
+
def parse_code( html, args, content = '' )
|
180
|
+
html.gsub(REGEX_EXTERNAL_TAG) do |s|
|
181
|
+
idx = $1.to_i
|
182
|
+
if idx > 0
|
183
|
+
(args[idx-1] || $2).to_s
|
184
|
+
elsif $3 == 'content'
|
185
|
+
parse_content content
|
186
|
+
else
|
187
|
+
"[#{tag}]"
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Tight
|
2
|
+
module Engine
|
3
|
+
module Template
|
4
|
+
def process_page
|
5
|
+
process_deferred_elements fragment( @page.fragment_id, :layout => :"layouts/#{@page.layout_id}" )
|
6
|
+
end
|
7
|
+
|
8
|
+
def element( name, *args )
|
9
|
+
opts = Hash === args.last ? args.pop : {}
|
10
|
+
defer_element( name, args, opts ) || process_element( name, args, opts )
|
11
|
+
end
|
12
|
+
|
13
|
+
def element_view( name, opts = {} )
|
14
|
+
fragment name, :elements, opts
|
15
|
+
end
|
16
|
+
|
17
|
+
def fragment( template, type = nil, opts = {} )
|
18
|
+
opts, type = type, nil if type.kind_of? Hash
|
19
|
+
opts[:layout] ||= false
|
20
|
+
type ||= :fragments
|
21
|
+
render :slim, :"#{type}/#{template}", opts
|
22
|
+
rescue Padrino::Rendering::TemplateNotFound, Errno::ENOENT => e
|
23
|
+
name = template.partition('/').first
|
24
|
+
report_error e, "EngineHelpers##{__method__}@#{__LINE__}", "[#{type.to_s.singularize.camelize} '#{name}' error: #{e.to_s.strip}]"
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def process_element( name, args, opts )
|
30
|
+
core, view = find_element name, opts[:instance]
|
31
|
+
fill_identity name, opts
|
32
|
+
catch :output do
|
33
|
+
@args, @opts = args, opts
|
34
|
+
binding.eval File.read(core), core if File.exists?(core)
|
35
|
+
render :slim, view.to_sym, :layout => false, :views => Swift::Application.views
|
36
|
+
end
|
37
|
+
rescue Padrino::Rendering::TemplateNotFound => e
|
38
|
+
report_error e, "EngineHelpers##{__method__}@#{__LINE__}", "[Element '#{name}' error: #{e.strip}]"
|
39
|
+
rescue Exception => e
|
40
|
+
report_error e, "EngineHelpers##{__method__}@#{__LINE__} '#{name}'"
|
41
|
+
end
|
42
|
+
|
43
|
+
def find_element( name, instance = nil )
|
44
|
+
view = "elements/#{name}/view"
|
45
|
+
if instance
|
46
|
+
instance_view = "#{view}-#{instance}"
|
47
|
+
view = instance_view if File.file?( "#{Swift::Application.views}/#{instance_view}.slim" )
|
48
|
+
end
|
49
|
+
[ "#{Swift::Application.views}/elements/#{name}/core.rb", view ]
|
50
|
+
end
|
51
|
+
|
52
|
+
def fill_identity( element_name, opts = {} )
|
53
|
+
@identity = { :class => element_name.dup }
|
54
|
+
@identity[:id] = opts[:id] if opts[:id]
|
55
|
+
@identity[:class] << " #{opts[:class]}" if opts[:class]
|
56
|
+
@identity[:class] << " #{element_name}-#{opts[:instance]}" if opts[:instance]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|