tight-engine 0.0.1 → 0.0.2
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/.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
|