rayo 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +15 -2
- data/lib/rayo/application.rb +65 -18
- data/lib/rayo/config.rb +22 -17
- data/lib/rayo/config/domain.rb +9 -1
- data/lib/rayo/config/format.rb +25 -0
- data/lib/rayo/models/page.rb +43 -10
- data/lib/rayo/models/renderable.rb +6 -2
- data/lib/rayo/storage.rb +26 -20
- data/lib/rayo/tag_context.rb +12 -0
- data/lib/rayo/tags/content_tags.rb +14 -3
- data/lib/rayo/tags/navigation_tags.rb +70 -21
- data/lib/rayo/tags/property_tags.rb +26 -2
- data/lib/rayo/version.rb +1 -1
- metadata +8 -6
data/README.rdoc
CHANGED
@@ -74,6 +74,10 @@ You may create generic pages which are rendered for a set of different paths. Fo
|
|
74
74
|
|
75
75
|
=== Built-In Tags
|
76
76
|
|
77
|
+
==== Hidden pages
|
78
|
+
|
79
|
+
If a page shouldn't be listed in children of parent page you may set property <tt>hidden</tt> to <tt>true</tt> in its yml file.
|
80
|
+
|
77
81
|
=== Filters
|
78
82
|
|
79
83
|
== Configuration
|
@@ -114,7 +118,7 @@ And register it:
|
|
114
118
|
|
115
119
|
c.add_tags MyTags
|
116
120
|
|
117
|
-
=== Multidomain
|
121
|
+
=== Multidomain setup
|
118
122
|
|
119
123
|
Sometimes you may want to serve different domains with one application sharing layouts and snippets. Rayo has built-in support for this scenario. All you need is to create subdirectories in pages for different domains and add some lines to <tt>configure</tt> block:
|
120
124
|
|
@@ -137,10 +141,19 @@ With both lines corresponding directory structure should be:
|
|
137
141
|
|
138
142
|
That's all you need to build multi-domain application.
|
139
143
|
|
144
|
+
== Caching
|
145
|
+
|
146
|
+
Rayo supports transparent caching of your generated pages in filesystem which is configured by one line, specifying cache directory:
|
147
|
+
|
148
|
+
c.cache_dir = 'your cache directory'
|
149
|
+
|
150
|
+
Every page after request are written to corresponding file in cache directory, so next requests will be served from there. And if you configure your web server to search for files in cache directory ruby application will not be touched at all.
|
151
|
+
|
152
|
+
For single-domain setups it may be useful to point <tt>cache_dir</tt> to the public location, so it will be served by web-server without additional configuration.
|
153
|
+
|
140
154
|
== Planned features
|
141
155
|
|
142
156
|
* Support for sites without I18n
|
143
|
-
* Support for different page formats
|
144
157
|
* Drop-in tag libary support
|
145
158
|
* Support for pages without .yml
|
146
159
|
* Generator which creates a set of static pages from content structure
|
data/lib/rayo/application.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'sinatra/base'
|
2
|
+
require 'ftools'
|
2
3
|
|
3
4
|
require File.join(File.dirname(__FILE__), 'storage.rb')
|
4
5
|
require File.join(File.dirname(__FILE__), 'config.rb')
|
@@ -20,31 +21,81 @@ class Rayo::Application < Sinatra::Base
|
|
20
21
|
self.class.config
|
21
22
|
end
|
22
23
|
|
23
|
-
get '/*' do |
|
24
|
-
cfg = config.domain( request.host ) # Config for current host
|
24
|
+
get '/*' do |url|
|
25
|
+
if cfg = config.domain( request.host ) # Config for current host
|
26
|
+
redir, lang, path, format = analyze_path url # Analyze path
|
25
27
|
|
26
|
-
|
27
|
-
path = path.split '/' # Split path into segments
|
28
|
+
redirect_to_page( lang || select_language, path, format ) if redir # Redirect if needed
|
28
29
|
|
29
|
-
|
30
|
+
format ||= cfg.default_format # Set default format if needed
|
30
31
|
|
31
|
-
|
32
|
-
|
32
|
+
cache_page cfg, lang, path, format do
|
33
|
+
storage = create_storage( cfg ) # Page storage
|
33
34
|
|
34
|
-
|
35
|
+
page = storage.page( lang, path ) # Find page by path
|
36
|
+
page = storage.status_page( lang, path, 404 ) unless page && page.file # Render 404 page if there are no page, or there are no file
|
35
37
|
|
36
|
-
|
37
|
-
|
38
|
-
page = storage.status_page( lang, path, 404 ) unless page && page.file # Render 404 page if there are no page, or there are no file
|
39
|
-
|
40
|
-
[ page[:status], page.render ] # Return page status and content
|
38
|
+
render_page page, format # Render found page with given format
|
39
|
+
end
|
41
40
|
else
|
42
|
-
|
41
|
+
not_found 'Page not found'
|
43
42
|
end
|
44
43
|
end
|
45
44
|
|
46
45
|
private
|
47
46
|
|
47
|
+
def render_page( page, format )
|
48
|
+
status page[:status] # Set response status
|
49
|
+
body page.render( format ) # Set response body
|
50
|
+
|
51
|
+
content_type format # Set Content-Type header
|
52
|
+
expires page[:expires] if page[:expires] # Set expires header
|
53
|
+
end
|
54
|
+
|
55
|
+
def redirect_to_page( lang, path, format )
|
56
|
+
url = '/' + [ lang || select_language, *path ].join('/')
|
57
|
+
url << '.' + format if format
|
58
|
+
|
59
|
+
redirect url
|
60
|
+
end
|
61
|
+
|
62
|
+
def cache_page( cfg, lang, path, format )
|
63
|
+
return yield unless cfg.cache_dir # Return block result if no cache directory set up
|
64
|
+
|
65
|
+
if path.empty?
|
66
|
+
file_path = File.join( cfg.cache_dir, lang, "index.#{format}" )
|
67
|
+
else
|
68
|
+
file_path = File.join( cfg.cache_dir, lang, path[0..-2], "#{path.last}.#{format}" )
|
69
|
+
end
|
70
|
+
|
71
|
+
if File.exists? file_path # If cached page exists
|
72
|
+
content_type format # Set Content-Type header
|
73
|
+
body File.read( file_path ) # Return its content as a body
|
74
|
+
else
|
75
|
+
yield # Render page
|
76
|
+
|
77
|
+
FileUtils.mkdir_p( File.dirname file_path ) # Create directory
|
78
|
+
File.open( file_path, 'w' ){|f| f.write body } # Write content
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def analyze_path( p )
|
83
|
+
path = p.split '/' # Split path into segments
|
84
|
+
redir = path.reject! {|e| e.empty? } # Clear path and detect empty segments
|
85
|
+
redir ||= p[-1..-1] == '/'
|
86
|
+
|
87
|
+
unless path.empty? # If path non-empty
|
88
|
+
if m = path.last.match( /^(.*)\.([^.]+)$/ ) # Detect format
|
89
|
+
format = m[2]
|
90
|
+
path[-1] = m[1]
|
91
|
+
end
|
92
|
+
|
93
|
+
lang = path.shift if config.languages.include? path.first # Detect language
|
94
|
+
end
|
95
|
+
|
96
|
+
[redir || lang.nil?, lang, path, format]
|
97
|
+
end
|
98
|
+
|
48
99
|
def create_storage( cfg )
|
49
100
|
Rayo::Storage.new( cfg )
|
50
101
|
end
|
@@ -53,8 +104,4 @@ class Rayo::Application < Sinatra::Base
|
|
53
104
|
config.languages.first
|
54
105
|
end
|
55
106
|
|
56
|
-
def redirect_to_lang( path )
|
57
|
-
redirect '/' + [ select_language, *path].join('/')
|
58
|
-
end
|
59
|
-
|
60
107
|
end
|
data/lib/rayo/config.rb
CHANGED
@@ -6,19 +6,21 @@ require File.join(File.dirname(__FILE__), 'tags/navigation_tags.rb')
|
|
6
6
|
class Rayo::Config
|
7
7
|
|
8
8
|
attr_accessor :content_dir
|
9
|
+
attr_accessor :cache_dir
|
10
|
+
|
9
11
|
attr_accessor :languages
|
10
12
|
attr_accessor :page_exts
|
11
13
|
|
14
|
+
attr_accessor :default_format
|
15
|
+
attr_accessor :default_domain
|
16
|
+
|
12
17
|
def initialize
|
13
18
|
@languages = ['en']
|
14
19
|
@page_exts = ['.yml']
|
15
20
|
|
16
|
-
@
|
21
|
+
@formats = {}
|
17
22
|
@domains = []
|
18
23
|
|
19
|
-
# Default filters
|
20
|
-
add_filter('html'){|source| source }
|
21
|
-
|
22
24
|
@tagger = Object.new
|
23
25
|
@tagger.extend Rayo::Taggable
|
24
26
|
|
@@ -26,6 +28,9 @@ class Rayo::Config
|
|
26
28
|
add_tags Rayo::Tags::PropertyTags
|
27
29
|
add_tags Rayo::Tags::ContentTags
|
28
30
|
add_tags Rayo::Tags::NavigationTags
|
31
|
+
|
32
|
+
# Default format
|
33
|
+
@default_format = 'html'
|
29
34
|
end
|
30
35
|
|
31
36
|
# Add tags defined in module
|
@@ -35,14 +40,6 @@ class Rayo::Config
|
|
35
40
|
@tagger.extend tag_module
|
36
41
|
end
|
37
42
|
|
38
|
-
# Add filter
|
39
|
-
#
|
40
|
-
# @param [String,Symbol] file extension
|
41
|
-
# @param [Proc] filter proc which accepts source and return it in processed form
|
42
|
-
def add_filter( ext, &filter )
|
43
|
-
@filters[".#{ext}"] = filter
|
44
|
-
end
|
45
|
-
|
46
43
|
# Add domain
|
47
44
|
#
|
48
45
|
# @param [String] domain name
|
@@ -60,22 +57,30 @@ class Rayo::Config
|
|
60
57
|
File.join( @content_dir, content_type.to_s )
|
61
58
|
end
|
62
59
|
|
63
|
-
|
64
|
-
|
60
|
+
# Add filter
|
61
|
+
#
|
62
|
+
# @param [String,Symbol] renderable file extension
|
63
|
+
# @param [String,Symbol] requested content format
|
64
|
+
# @param [Proc] filter proc which accepts source and return it in processed form
|
65
|
+
def add_filter( from, to = nil, &filter )
|
66
|
+
format( to ).add_filter( from, &filter )
|
65
67
|
end
|
66
68
|
|
67
|
-
def
|
68
|
-
|
69
|
+
def format( name = nil )
|
70
|
+
name ||= default_format
|
71
|
+
|
72
|
+
@formats[name.to_s] ||= Rayo::Config::Format.new name
|
69
73
|
end
|
70
74
|
|
71
75
|
def domain( host )
|
72
76
|
if @domains.empty?
|
73
77
|
self # No multidomain support
|
74
78
|
else
|
75
|
-
@domains.find { |domain| domain.matches? host }
|
79
|
+
@domains.find { |domain| domain.matches? host } || @domains.find { |domain| domain.name == @default_domain }
|
76
80
|
end
|
77
81
|
end
|
78
82
|
|
79
83
|
end
|
80
84
|
|
81
85
|
require File.join(File.dirname(__FILE__), 'config/domain.rb')
|
86
|
+
require File.join(File.dirname(__FILE__), 'config/format.rb')
|
data/lib/rayo/config/domain.rb
CHANGED
@@ -4,7 +4,10 @@ class Rayo::Config::Domain
|
|
4
4
|
|
5
5
|
extend Forwardable
|
6
6
|
|
7
|
-
def_delegators :@parent, :create_tagger, :languages, :page_exts, :
|
7
|
+
def_delegators :@parent, :create_tagger, :languages, :page_exts, :format, :default_format
|
8
|
+
|
9
|
+
attr_reader :name
|
10
|
+
attr_writer :cache_dir
|
8
11
|
|
9
12
|
def initialize( parent, name, exp )
|
10
13
|
@parent = parent
|
@@ -24,4 +27,9 @@ class Rayo::Config::Domain
|
|
24
27
|
end
|
25
28
|
end
|
26
29
|
|
30
|
+
# Get cache directory for this domain. If it was not set explicitly it'll be global cache_dir with domain name appended
|
31
|
+
def cache_dir
|
32
|
+
@cache_dir || @parent.cache_dir && File.join( @parent.cache_dir, @name )
|
33
|
+
end
|
34
|
+
|
27
35
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
class Rayo::Config::Format
|
2
|
+
|
3
|
+
attr_reader :name
|
4
|
+
attr_reader :renderable_exts
|
5
|
+
|
6
|
+
def initialize( name )
|
7
|
+
@name = name.to_s
|
8
|
+
@filters = { @name => lambda{|source| source} }
|
9
|
+
@renderable_exts = [ ".#{name}" ]
|
10
|
+
end
|
11
|
+
|
12
|
+
# Add filter
|
13
|
+
#
|
14
|
+
# @param [String,Symbol] renderable file extension
|
15
|
+
# @param [Proc] filter proc which accepts source and return it in processed form
|
16
|
+
def add_filter( from, &filter )
|
17
|
+
@filters[from.to_s] = filter
|
18
|
+
@renderable_exts << ".#{from}" unless @renderable_exts.include? ".#{from}"
|
19
|
+
end
|
20
|
+
|
21
|
+
def filter( from )
|
22
|
+
@filters[from.to_s]
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
data/lib/rayo/models/page.rb
CHANGED
@@ -13,6 +13,9 @@ class Rayo::Models::Page
|
|
13
13
|
@parent = parent
|
14
14
|
@lang = lang
|
15
15
|
@path = path
|
16
|
+
|
17
|
+
@parts = {}
|
18
|
+
@layouts = {}
|
16
19
|
end
|
17
20
|
|
18
21
|
def descendant( relative_path )
|
@@ -27,6 +30,18 @@ class Rayo::Models::Page
|
|
27
30
|
@children ||= @storage.find_pages( directories, @lang ).map{|name| child( name ) }
|
28
31
|
end
|
29
32
|
|
33
|
+
def relative( url )
|
34
|
+
path = url.split '/'
|
35
|
+
|
36
|
+
if path.empty?
|
37
|
+
@storage.root_page( @lang )
|
38
|
+
elsif path.first && path.first.empty?
|
39
|
+
@storage.root_page( @lang ).descendant( path[1..-1] )
|
40
|
+
else
|
41
|
+
descendant( path )
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
30
45
|
def child( slug )
|
31
46
|
@children_cache ||= {}
|
32
47
|
return @children_cache[ slug ] if @children_cache.include? slug
|
@@ -45,17 +60,25 @@ class Rayo::Models::Page
|
|
45
60
|
@file ||= @storage.find_page_file( @parent.directories, @lang, @path.last )
|
46
61
|
end
|
47
62
|
|
48
|
-
|
49
|
-
|
63
|
+
# Get page parts for given format
|
64
|
+
# @param [String,Symbol] part format
|
65
|
+
# @return [List<Rayo::Models::Renderable>] part list
|
66
|
+
def parts( format )
|
67
|
+
@parts[format.to_s] ||= file ? @storage.find_page_parts( file, @lang, format.to_s ) : {}
|
50
68
|
end
|
51
69
|
|
52
|
-
|
70
|
+
# Find page part for given format
|
71
|
+
# @param [String,Symbol] part format
|
72
|
+
# @param [String,Symbol] part name
|
73
|
+
# @param [Boolean] search in super classes
|
74
|
+
# @return [List<Rayo::Models::Renderable>] part list
|
75
|
+
def find_part( format, part_name, inherit = false )
|
53
76
|
page = self
|
54
|
-
part = self.parts[part_name]
|
77
|
+
part = self.parts(format)[part_name]
|
55
78
|
|
56
79
|
while inherit && !part && page.parent do
|
57
80
|
page = page.parent
|
58
|
-
part = page.parts[part_name]
|
81
|
+
part = page.parts(format)[part_name]
|
59
82
|
end
|
60
83
|
|
61
84
|
part
|
@@ -84,8 +107,8 @@ class Rayo::Models::Page
|
|
84
107
|
@context
|
85
108
|
end
|
86
109
|
|
87
|
-
def layout
|
88
|
-
@
|
110
|
+
def layout(format)
|
111
|
+
@layouts[format.to_s] ||= @storage.layout( @lang, context['layout'], format )
|
89
112
|
end
|
90
113
|
|
91
114
|
def []( key )
|
@@ -94,8 +117,12 @@ class Rayo::Models::Page
|
|
94
117
|
context[ key ] || params[ key ]
|
95
118
|
end
|
96
119
|
|
97
|
-
def render
|
98
|
-
layout
|
120
|
+
def render( format )
|
121
|
+
if l = layout( format )
|
122
|
+
l.render( parser )
|
123
|
+
else
|
124
|
+
"Layout: '#{context['layout']}'' not found with format '#{format}'"
|
125
|
+
end
|
99
126
|
end
|
100
127
|
|
101
128
|
def parser
|
@@ -105,7 +132,13 @@ class Rayo::Models::Page
|
|
105
132
|
private
|
106
133
|
|
107
134
|
def load_context( filename )
|
108
|
-
|
135
|
+
cont = @storage.load( filename )
|
136
|
+
|
137
|
+
if cont && !cont.strip.empty?
|
138
|
+
YAML::load( Erubis::Eruby.new( cont ).result( params ) )
|
139
|
+
else
|
140
|
+
{}
|
141
|
+
end
|
109
142
|
end
|
110
143
|
|
111
144
|
end
|
@@ -2,11 +2,13 @@ class Rayo::Models::Renderable
|
|
2
2
|
|
3
3
|
attr_reader :storage
|
4
4
|
attr_reader :file
|
5
|
+
attr_reader :format
|
5
6
|
attr_reader :filter
|
6
7
|
|
7
|
-
def initialize( storage, file, filter )
|
8
|
+
def initialize( storage, file, format, filter )
|
8
9
|
@storage = storage
|
9
10
|
@file = file
|
11
|
+
@format = format
|
10
12
|
@filter = filter
|
11
13
|
end
|
12
14
|
|
@@ -15,7 +17,9 @@ class Rayo::Models::Renderable
|
|
15
17
|
end
|
16
18
|
|
17
19
|
def render( parser )
|
18
|
-
|
20
|
+
parser.context.with_format @format do
|
21
|
+
filter.call( parser.parse( source ) )
|
22
|
+
end
|
19
23
|
end
|
20
24
|
|
21
25
|
end
|
data/lib/rayo/storage.rb
CHANGED
@@ -13,12 +13,12 @@ class Rayo::Storage
|
|
13
13
|
@snippets = {}
|
14
14
|
end
|
15
15
|
|
16
|
-
def snippet( lang, name )
|
17
|
-
@snippets["#{lang}|#{name}"] ||= find_renderable( :snippets, lang, name.to_s
|
16
|
+
def snippet( lang, name, format )
|
17
|
+
@snippets["#{lang}|#{name}|#{format}"] ||= find_renderable( :snippets, lang, name.to_s, format )
|
18
18
|
end
|
19
19
|
|
20
|
-
def layout( lang, name )
|
21
|
-
@layouts["#{lang}|#{name}"] ||= find_renderable( :layouts, lang, name.to_s
|
20
|
+
def layout( lang, name, format )
|
21
|
+
@layouts["#{lang}|#{name}|#{format}"] ||= find_renderable( :layouts, lang, name.to_s, format )
|
22
22
|
end
|
23
23
|
|
24
24
|
# Retrieves root page for specific language
|
@@ -47,14 +47,14 @@ class Rayo::Storage
|
|
47
47
|
Rayo::Models::StatusPage.new( self, root_page( lang ), path, status )
|
48
48
|
end
|
49
49
|
|
50
|
-
def find_renderable( type, lang, name )
|
51
|
-
if file = find_file( [config.directory( type )], lang, name, config.renderable_exts )
|
52
|
-
renderable( file, File.extname( file ) )
|
50
|
+
def find_renderable( type, lang, name, format )
|
51
|
+
if file = find_file( [config.directory( type )], lang, name, config.format( format ).renderable_exts )
|
52
|
+
renderable( file, format, File.extname( file ) )
|
53
53
|
end
|
54
54
|
end
|
55
55
|
|
56
56
|
def find_page_file( dirs, lang, slug )
|
57
|
-
find_file( dirs, lang, slug, config.page_exts )
|
57
|
+
find_file( dirs, lang, slug, config.page_exts, true )
|
58
58
|
end
|
59
59
|
|
60
60
|
def find_page_dirs( dirs, lang, slug )
|
@@ -68,28 +68,28 @@ class Rayo::Storage
|
|
68
68
|
elem_name = elems[0]
|
69
69
|
elem_lang = elems[1]
|
70
70
|
|
71
|
-
res << elem_name unless elem_name[0..0]
|
71
|
+
res << elem_name unless ['%','_'].include?( elem_name[0..0] ) || (dirs == ([ @config.directory :pages ]) && (elem_name == 'index')) || (elem_lang && elem_lang != lang)
|
72
72
|
end
|
73
73
|
res.uniq
|
74
74
|
end
|
75
75
|
|
76
|
-
def find_page_parts( page_file, lang )
|
76
|
+
def find_page_parts( page_file, lang, format )
|
77
77
|
parts = {}
|
78
78
|
page_file_base = File.basename( page_file ).split('.').first
|
79
|
-
glob_files File.dirname( page_file ), lang, page_file_base + '*', config.renderable_exts do |file,base,ext|
|
79
|
+
glob_files File.dirname( page_file ), lang, page_file_base + '*', config.format( format ).renderable_exts do |file,base,ext|
|
80
80
|
elems = base.split('.')
|
81
81
|
|
82
82
|
if elems.shift == page_file_base # Remove base (slug or variable)
|
83
83
|
if elems.size == 0 # There are no part name and language
|
84
|
-
parts[ 'body' ] ||= renderable( file, ext )
|
84
|
+
parts[ 'body' ] ||= renderable( file, format, ext )
|
85
85
|
elsif elems.size == 1 # There are no language or no part name
|
86
86
|
if elems[0] == lang
|
87
|
-
parts[ 'body' ] ||= renderable( file, ext )
|
87
|
+
parts[ 'body' ] ||= renderable( file, format, ext )
|
88
88
|
else
|
89
|
-
parts[ elems[0] ] ||= renderable( file, ext )
|
89
|
+
parts[ elems[0] ] ||= renderable( file, format, ext )
|
90
90
|
end
|
91
91
|
else
|
92
|
-
parts[ elems[0] ] ||= renderable( file, ext ) if elems[1] == lang
|
92
|
+
parts[ elems[0] ] ||= renderable( file, format, ext ) if elems[1] == lang
|
93
93
|
end
|
94
94
|
end
|
95
95
|
end
|
@@ -102,13 +102,13 @@ class Rayo::Storage
|
|
102
102
|
|
103
103
|
private
|
104
104
|
|
105
|
-
def renderable( file, ext )
|
106
|
-
Rayo::Models::Renderable.new( self, file, config.filter( ext ) || raise( "Filter for '#{ext} not found" ) )
|
105
|
+
def renderable( file, format, ext )
|
106
|
+
Rayo::Models::Renderable.new( self, file, format, config.format( format ).filter( ext[1..-1] ) || raise( "Filter for '#{ext} not found" ) )
|
107
107
|
end
|
108
108
|
|
109
109
|
# Find first file with given name (or variable) and extension from given set
|
110
|
-
def find_file( dirs, lang, name, exts )
|
111
|
-
glob_files( dirs, lang, name, exts ) { |file,base,ext| return file }
|
110
|
+
def find_file( dirs, lang, name, exts, hidden = false )
|
111
|
+
glob_files( dirs, lang, name, exts, hidden ) { |file,base,ext| return file }
|
112
112
|
nil
|
113
113
|
end
|
114
114
|
|
@@ -119,11 +119,17 @@ class Rayo::Storage
|
|
119
119
|
results
|
120
120
|
end
|
121
121
|
|
122
|
-
def glob_files( dirs, lang, name, exts, &block )
|
122
|
+
def glob_files( dirs, lang, name, exts, hidden = false, &block )
|
123
123
|
lang_prefix = "." + lang
|
124
124
|
|
125
125
|
glob dirs, name + lang_prefix, //, exts, &block # Search with given name and language
|
126
126
|
glob dirs, name, //, exts, &block # Search with given name without language
|
127
|
+
|
128
|
+
if hidden
|
129
|
+
glob dirs, '_' + name + lang_prefix, //, exts, &block # Search hidden with given name and language
|
130
|
+
glob dirs, '_' + name, //, exts, &block # Search hidden with given name without language
|
131
|
+
end
|
132
|
+
|
127
133
|
glob dirs, '%*' + lang_prefix, /^%.+\.#{lang}$/, exts, &block # Search with variable and language
|
128
134
|
glob dirs, '%*', /^%.+$/, exts, &block # Search with variable without language
|
129
135
|
end
|
data/lib/rayo/tag_context.rb
CHANGED
@@ -9,6 +9,7 @@ class Rayo::TagContext < Radius::Context
|
|
9
9
|
|
10
10
|
globals.page = @page
|
11
11
|
globals.storage = @page.storage
|
12
|
+
globals.config = @page.storage.config
|
12
13
|
|
13
14
|
tagger = @page.storage.config.create_tagger
|
14
15
|
tagger.methods.each do |name|
|
@@ -32,4 +33,15 @@ class Rayo::TagContext < Radius::Context
|
|
32
33
|
"<strong class=\"error\">#{text}</strong>"
|
33
34
|
end
|
34
35
|
|
36
|
+
def with_format( format )
|
37
|
+
old_format = globals.format
|
38
|
+
globals.format = format
|
39
|
+
|
40
|
+
result = yield
|
41
|
+
|
42
|
+
globals.format = old_format
|
43
|
+
|
44
|
+
result
|
45
|
+
end
|
46
|
+
|
35
47
|
end
|
@@ -24,7 +24,7 @@ module Rayo::Tags::ContentTags
|
|
24
24
|
tag.globals.layout_stack ||= [] # Prepare layout stack
|
25
25
|
tag.globals.content_stack ||= [] # Prepare content stack
|
26
26
|
|
27
|
-
if layout = tag.globals.storage.layout( tag.globals.page.lang, name )
|
27
|
+
if layout = tag.globals.storage.layout( tag.globals.page.lang, name, tag.globals.format )
|
28
28
|
tag.globals.layout_stack << name # Track this layout on the stack
|
29
29
|
tag.globals.content_stack << tag.expand # Save contents of inside_layout for later insertion
|
30
30
|
|
@@ -39,7 +39,7 @@ module Rayo::Tags::ContentTags
|
|
39
39
|
|
40
40
|
tag 'snippet' do |tag|
|
41
41
|
snippet_name = tag.attr['name']
|
42
|
-
snippet = tag.globals.storage.snippet( tag.globals.page.lang, snippet_name )
|
42
|
+
snippet = tag.globals.storage.snippet( tag.globals.page.lang, snippet_name, tag.attr['format'] || tag.globals.format )
|
43
43
|
|
44
44
|
if snippet
|
45
45
|
snippet.render( tag.globals.page.parser )
|
@@ -48,10 +48,21 @@ module Rayo::Tags::ContentTags
|
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
|
+
tag 'with' do |tag|
|
52
|
+
old_format = tag.globals.format
|
53
|
+
tag.globals.format = tag.attr['format']
|
54
|
+
|
55
|
+
result = tag.expand
|
56
|
+
|
57
|
+
tag.globals.format = old_format
|
58
|
+
|
59
|
+
result
|
60
|
+
end
|
61
|
+
|
51
62
|
private
|
52
63
|
|
53
64
|
def find_part( tag )
|
54
|
-
tag.locals.page.find_part( tag.attr['part'] || 'body', tag.attr['inherit'] == 'true' )
|
65
|
+
tag.locals.page.find_part( tag.attr['format'] || tag.globals.format, tag.attr['part'] || 'body', tag.attr['inherit'] == 'true' )
|
55
66
|
end
|
56
67
|
|
57
68
|
end
|
@@ -3,19 +3,7 @@ module Rayo::Tags::NavigationTags
|
|
3
3
|
include Rayo::Taggable
|
4
4
|
|
5
5
|
tag 'find' do |tag|
|
6
|
-
|
7
|
-
path = url.split('/')
|
8
|
-
|
9
|
-
if path.first.empty?
|
10
|
-
path.shift
|
11
|
-
page = tag.locals.page.storage.root_page( tag.globals.page.lang )
|
12
|
-
else
|
13
|
-
page = tag.locals.page
|
14
|
-
end
|
15
|
-
|
16
|
-
page = page.descendant( path )
|
17
|
-
|
18
|
-
if page
|
6
|
+
if page = tag.locals.page.relative( tag.attr['url'] )
|
19
7
|
tag.locals.page = page
|
20
8
|
tag.expand
|
21
9
|
else
|
@@ -24,40 +12,101 @@ module Rayo::Tags::NavigationTags
|
|
24
12
|
end
|
25
13
|
|
26
14
|
tag 'children' do |tag|
|
27
|
-
|
15
|
+
children = tag.locals.page.children
|
16
|
+
|
17
|
+
[ tag.attr['level'].to_i - 1, 0 ].max.times do
|
18
|
+
children = children.map{ |p| p.children }.flatten
|
19
|
+
end
|
20
|
+
|
21
|
+
tag.locals.children = children
|
28
22
|
tag.expand
|
29
23
|
end
|
30
24
|
|
31
25
|
tag 'children:count' do |tag|
|
32
|
-
tag.
|
26
|
+
prepare_children( tag ).size
|
33
27
|
end
|
34
28
|
|
35
29
|
tag 'children:first' do |tag|
|
36
|
-
if first = tag.
|
30
|
+
if first = prepare_children( tag ).first
|
37
31
|
tag.locals.page = first
|
38
32
|
tag.expand
|
39
33
|
end
|
40
34
|
end
|
41
35
|
|
42
36
|
tag 'children:last' do |tag|
|
43
|
-
if
|
44
|
-
tag.locals.page =
|
37
|
+
if last = prepare_children( tag ).last
|
38
|
+
tag.locals.page = last
|
45
39
|
tag.expand
|
46
40
|
end
|
47
41
|
end
|
48
42
|
|
49
43
|
tag 'children:each' do |tag|
|
50
|
-
result =
|
44
|
+
result = ""
|
45
|
+
children = prepare_children( tag )
|
51
46
|
|
52
|
-
children = tag.locals.children
|
53
47
|
children.each_with_index do |item, i|
|
54
48
|
tag.locals.child = item
|
55
49
|
tag.locals.page = item
|
56
50
|
tag.locals.first_child = i == 0
|
57
|
-
tag.locals.last_child = i == children.
|
51
|
+
tag.locals.last_child = i == children.size - 1
|
52
|
+
|
53
|
+
result << tag.expand
|
54
|
+
end
|
55
|
+
result
|
56
|
+
end
|
57
|
+
|
58
|
+
tag 'related' do |tag|
|
59
|
+
tag.locals.relation = tag.locals.page['relations'][tag.attr['rel']]
|
60
|
+
tag.expand
|
61
|
+
end
|
62
|
+
|
63
|
+
tag 'related:count' do |tag|
|
64
|
+
tag.locals.relation.size
|
65
|
+
end
|
66
|
+
|
67
|
+
tag 'related:first' do |tag|
|
68
|
+
if first = tag.locals.relation.first
|
69
|
+
tag.locals.page = tag.locals.page.relative first
|
70
|
+
tag.expand
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
tag 'related:last' do |tag|
|
75
|
+
if last = tag.locals.relation.last
|
76
|
+
tag.locals.page = tag.locals.page.relative last
|
77
|
+
tag.expand
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
tag 'related:each' do |tag|
|
82
|
+
result = ''
|
83
|
+
|
84
|
+
relation = tag.locals.relation
|
85
|
+
relation.each_with_index do |item, i|
|
86
|
+
tag.locals.page = tag.locals.page.relative item
|
87
|
+
tag.locals.first_related = i == 0
|
88
|
+
tag.locals.last_related = i == relation.size - 1
|
89
|
+
|
58
90
|
result << tag.expand
|
59
91
|
end
|
60
92
|
result
|
61
93
|
end
|
62
94
|
|
95
|
+
private
|
96
|
+
|
97
|
+
def prepare_children( tag )
|
98
|
+
children = tag.locals.children
|
99
|
+
|
100
|
+
if by = tag.attr['by']
|
101
|
+
if tag.attr['order'] == 'desc'
|
102
|
+
children = children.sort {|a,b| b[by] <=> a[by] }
|
103
|
+
else
|
104
|
+
children = children.sort {|a,b| a[by] <=> b[by] }
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
children = children[0..(tag.attr['limit'].to_i - 1)] if tag.attr['limit']
|
109
|
+
children
|
110
|
+
end
|
111
|
+
|
63
112
|
end
|
@@ -10,6 +10,10 @@ module Rayo::Tags::PropertyTags
|
|
10
10
|
tag.locals.page.context['description']
|
11
11
|
end
|
12
12
|
|
13
|
+
tag 'value' do |tag|
|
14
|
+
tag.locals.page[tag.attr['name']]
|
15
|
+
end
|
16
|
+
|
13
17
|
tag 'path' do |tag|
|
14
18
|
basepath = tag.globals.page.path
|
15
19
|
path = tag.locals.page.path
|
@@ -24,10 +28,16 @@ module Rayo::Tags::PropertyTags
|
|
24
28
|
i = i + 1
|
25
29
|
end
|
26
30
|
|
27
|
-
'../' * (basepath.size - i) + path[i..-1].join('/')
|
31
|
+
'./' + ('../' * (basepath.size - i)) + path[i..-1].join('/')
|
28
32
|
end
|
29
33
|
end
|
30
34
|
|
35
|
+
tag 'url' do |tag|
|
36
|
+
u = "/#{tag.locals.page.lang}/#{tag.locals.page.path.join('/')}"
|
37
|
+
u << ".#{tag.globals.format}" if tag.globals.format != tag.globals.config.default_format
|
38
|
+
u
|
39
|
+
end
|
40
|
+
|
31
41
|
tag 'link' do |tag|
|
32
42
|
"<a href=\"#{send 'tag:path', tag}\">#{tag.single? ? send( 'tag:title', tag ) : tag.expand}</a>"
|
33
43
|
end
|
@@ -41,11 +51,25 @@ module Rayo::Tags::PropertyTags
|
|
41
51
|
end
|
42
52
|
|
43
53
|
tag 'date' do |tag|
|
44
|
-
|
54
|
+
date_for( tag ).strftime( tag.attr['format'] || '%A, %B %d, %Y' )
|
55
|
+
end
|
56
|
+
|
57
|
+
tag 'rfc1123_date' do |tag|
|
58
|
+
CGI.rfc1123_date( date_for( tag ) )
|
45
59
|
end
|
46
60
|
|
47
61
|
private
|
48
62
|
|
63
|
+
def date_for( tag )
|
64
|
+
if tag.attr['for'] == 'now'
|
65
|
+
Time.now
|
66
|
+
elsif tag.attr['for']
|
67
|
+
tag.locals.page[tag.attr['for']]
|
68
|
+
else
|
69
|
+
tag.locals.page['published_at']
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
49
73
|
def if_url( tag )
|
50
74
|
tag.locals.page.path =~ Regexp.new( tag.attr['matches'] )
|
51
75
|
end
|
data/lib/rayo/version.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rayo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 19
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
8
|
+
- 3
|
9
9
|
- 0
|
10
|
-
version: 0.
|
10
|
+
version: 0.3.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Alexey Noskov
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-11-
|
18
|
+
date: 2010-11-20 00:00:00 +03:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -54,11 +54,12 @@ dependencies:
|
|
54
54
|
requirements:
|
55
55
|
- - ">="
|
56
56
|
- !ruby/object:Gem::Version
|
57
|
-
hash:
|
57
|
+
hash: 19
|
58
58
|
segments:
|
59
59
|
- 1
|
60
|
+
- 1
|
60
61
|
- 0
|
61
|
-
version:
|
62
|
+
version: 1.1.0
|
62
63
|
type: :runtime
|
63
64
|
version_requirements: *id003
|
64
65
|
- !ruby/object:Gem::Dependency
|
@@ -102,6 +103,7 @@ extra_rdoc_files:
|
|
102
103
|
- MIT-LICENSE
|
103
104
|
files:
|
104
105
|
- lib/rayo.rb
|
106
|
+
- lib/rayo/config/format.rb
|
105
107
|
- lib/rayo/config/domain.rb
|
106
108
|
- lib/rayo/storage.rb
|
107
109
|
- lib/rayo/application.rb
|