tanuki 0.1.3

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.
@@ -0,0 +1,145 @@
1
+ module Tanuki
2
+
3
+ # Tanuki::TemplateCompiler is used for, well, compiling templates.
4
+ class TemplateCompiler
5
+
6
+ class << self
7
+
8
+ # Compiles a template from a given src string to ios for method sym in class klass.
9
+ def compile_template(ios, src, klass, sym)
10
+ ios << "# encoding: #{src.encoding}\nclass #{klass}\ndef #{sym}_view(*args,&block)\nproc do|_,ctx|\n" \
11
+ "if _has_tpl ctx,self.class,:#{sym}\nctx=_ctx(ctx)"
12
+ last_state = compile(ios, src)
13
+ ios << "\n_.call('',ctx)" unless PRINT_STATES.include? last_state
14
+ ios << "\nelse\n(_run_tpl ctx,self,:#{sym},*args,&block).call(_,ctx)\nend\nend\nend\nend"
15
+ end
16
+
17
+ # Compiles code from a given src string to ios.
18
+ def compile(ios, src)
19
+ state = :outer
20
+ last_state = nil
21
+ index = 0
22
+ trim_newline = false
23
+ code_buf = ''
24
+ begin
25
+ if new_index = src[index..-1].index(pattern = expect_pattern(state))
26
+ new_index += index
27
+ match = src[index..-1].match(pattern)[0]
28
+ new_state = next_state(state, match)
29
+ else
30
+ new_state = nil
31
+ end
32
+ if state == :outer
33
+ s = new_index ? src[index, new_index - index] : src[index..-1]
34
+ if trim_newline && !s.empty?
35
+ s[0] = '' if s[0] == "\n"
36
+ trim_newline = false
37
+ end
38
+ if new_state == :code_skip
39
+ code_buf << s.dup << match[0..-2]
40
+ index = new_index + match.length
41
+ next
42
+ elsif not s.empty?
43
+ ios << "\n_.call(#{(code_buf << s).inspect},ctx)"
44
+ code_buf = ''
45
+ end
46
+ end
47
+ if new_index
48
+ unless state != :outer && new_state == :code_skip
49
+ if new_state == :outer
50
+ process_code_state(ios, code_buf << src[index...new_index], state)
51
+ code_buf = ''
52
+ end
53
+ index = new_index + match.length
54
+ trim_newline = true if (match == '-%>')
55
+ last_state = state unless state == :code_comment
56
+ state = new_state
57
+ else
58
+ code_buf << src[index...new_index] << '%>'
59
+ index = new_index + match.length
60
+ end
61
+ end
62
+ end until new_index.nil?
63
+ last_state
64
+ end
65
+
66
+ private
67
+
68
+ # Scanner states that output the evaluated result.
69
+ PRINT_STATES = [:outer, :code_print]
70
+
71
+ def process_code_state(ios, src, state)
72
+ src.strip!
73
+ src.gsub! /^[ \t]+/, ''
74
+ case state
75
+ when :code_line, :code_span then
76
+ ios << "\n#{src}"
77
+ when :code_print then
78
+ ios << "\n_.call((#{src}),ctx)"
79
+ when :code_template then
80
+ ios << "\n(#{src}).call(_,ctx)"
81
+ when :code_visitor
82
+ inner_m = src.match /^([^ \(]+)?(\([^\)]*\))?\s*(.*)$/
83
+ ios << "\n#{inner_m[1]}_result=(#{inner_m[3]}).call(#{inner_m[1]}_visitor#{inner_m[2]},ctx)"
84
+ when :l10n then
85
+ localize(ios, src)
86
+ end
87
+ end
88
+
89
+ # Returns the next expected pattern for a given state.
90
+ def expect_pattern(state)
91
+ case state
92
+ when :outer then %r{^\s*%%?|<%[=!_#%]?|<l10n>}
93
+ when :code_line then %r{\n|\Z}
94
+ when :code_span, :code_print, :code_template, :code_visitor, :code_comment then %r{[-%]?%>}
95
+ when :l10n then %r{<\/l10n>}
96
+ end
97
+ end
98
+
99
+ # Returns the next state for a given match and current state.
100
+ def next_state(state, match)
101
+ case state
102
+ when :outer then
103
+ case match
104
+ when /\A\s*%\Z/ then :code_line
105
+ when /\A\s*%%\Z/ then :code_skip
106
+ when '<%' then :code_span
107
+ when '<%=' then :code_print
108
+ when '<%!' then :code_template
109
+ when '<%_' then :code_visitor
110
+ when '<%#' then :code_comment
111
+ when '<%%' then :code_skip
112
+ when '<l10n>' then :l10n
113
+ end
114
+ when :code_line then :outer
115
+ when :code_span, :code_print, :code_template, :code_visitor, :code_comment then
116
+ case match
117
+ when '%%>' then :code_skip
118
+ else :outer
119
+ end
120
+ when :l10n then :outer
121
+ end
122
+ end
123
+
124
+ # Generates localization code from src.
125
+ def localize(ios, src)
126
+ index = 0
127
+ lngs = []
128
+ ios << "\ncase ctx.best_language "
129
+ code = StringIO.new
130
+ while index = src.index(/<[a-z]{2}>/, index)
131
+ lngs << (lng = src[index + 1, 2].to_sym)
132
+ if end_index = src.index(/<\/#{lng}>/, index += 4)
133
+ code << "\nwhen #{lng.inspect} then"
134
+ compile(code, src[index...end_index])
135
+ index = end_index + 5
136
+ end
137
+ end
138
+ ios << "#{lngs.inspect.gsub(/ /, '')}#{code.string}\nend"
139
+ end
140
+
141
+ end # end class << self
142
+
143
+ end # end TemplateCompiler
144
+
145
+ end # end Tanuki
@@ -0,0 +1,6 @@
1
+ module Tanuki
2
+
3
+ # Tanuki framework version.
4
+ VERSION = '0.1.3'
5
+
6
+ end # end Tanuki
data/lib/tanuki.rb ADDED
@@ -0,0 +1,22 @@
1
+ module Tanuki
2
+ libdir = File.dirname(__FILE__)
3
+ $:.unshift(libdir) unless $:.include?(libdir)
4
+ end
5
+
6
+ require 'rack'
7
+ require 'fileutils'
8
+ require 'yaml'
9
+ require 'escape_utils'
10
+ require 'escape_utils/url/rack'
11
+ require 'tanuki/version'
12
+ require 'tanuki/module_extensions'
13
+ require 'tanuki/argument'
14
+ require 'tanuki/configurator'
15
+ require 'tanuki/context'
16
+ require 'tanuki/controller_behavior'
17
+ require 'tanuki/launcher'
18
+ require 'tanuki/loader'
19
+ require 'tanuki/i18n'
20
+ require 'tanuki/object_behavior'
21
+ require 'tanuki/template_compiler'
22
+ require 'tanuki/application'
@@ -0,0 +1,13 @@
1
+ ---
2
+ numeral: [controller, controllers]
3
+ plural: controllers
4
+ attributes:
5
+ class:
6
+ title: class
7
+ description: Controller class name
8
+ title:
9
+ title: title
10
+ description: Readable controller title
11
+ pages:
12
+ title: pages
13
+ description: Pages with this controller
@@ -0,0 +1,31 @@
1
+ ---
2
+ numeral: [page, pages]
3
+ plural: pages
4
+ attributes:
5
+ parent:
6
+ title: parent
7
+ description: Parent page
8
+ children:
9
+ title: children
10
+ description: Child pages
11
+ title:
12
+ title: title
13
+ description: Short page title
14
+ long_title:
15
+ title: long title
16
+ description: Long page title
17
+ content:
18
+ title: content
19
+ description: Page content
20
+ controller:
21
+ title: controller
22
+ description: Page creation logic
23
+ default_route:
24
+ title: default route
25
+ description: Path to main child page
26
+ use_default_route:
27
+ title: use default route
28
+ description: Use path to main child page
29
+ hidden:
30
+ title: hidden
31
+ description: Page is hidden or not
@@ -0,0 +1,13 @@
1
+ ---
2
+ numeral: [контроллер, контроллера, контроллеров]
3
+ plural: контроллеры
4
+ attributes:
5
+ class:
6
+ title: класс
7
+ description: Имя класса контроллера
8
+ title:
9
+ title: название
10
+ description: Читабельное название контроллера
11
+ pages:
12
+ title: страницы
13
+ description: Страницы, управляемые данным контроллером
@@ -0,0 +1,31 @@
1
+ ---
2
+ numeral: [страница, страницы, страниц]
3
+ plural: страницы
4
+ attributes:
5
+ parent:
6
+ title: родитель
7
+ description: Родительская страница
8
+ children:
9
+ title: дети
10
+ description: Дочерние страницы
11
+ title:
12
+ title: заголовок
13
+ description: Краткий заголовок страницы
14
+ long_title:
15
+ title: детальный заголовок
16
+ description: Детальный заголовок страницы
17
+ content:
18
+ title: содержимое
19
+ description: Содержимое страницы
20
+ controller:
21
+ title: контроллер
22
+ description: Программа, формирующая страницу
23
+ default_route:
24
+ title: переход
25
+ description: Путь к главной дочерней странице
26
+ use_default_route:
27
+ title: использовать переход
28
+ description: Переходить к главной дочерней странице
29
+ hidden:
30
+ title: скрыта
31
+ description: Скрыта страница или нет
@@ -0,0 +1,18 @@
1
+ ---
2
+ namespaces:
3
+ default: Tanuki
4
+ source:
5
+ table: tanuki_controllers
6
+ alias: tc
7
+ key: tc.class
8
+ to_s: tc.title
9
+ attributes:
10
+ class: { type: String, size: 80, required: true }
11
+ title: { type: String, required: true }
12
+ pages: { type: Collection }
13
+ l10n:
14
+ adapter: Shadow
15
+ table: tanuki_controllers_l10n
16
+ list:
17
+ class: { link: true }
18
+ title: ~
@@ -0,0 +1,48 @@
1
+ ---
2
+ namespaces:
3
+ default: Tanuki
4
+ source:
5
+ table: tanuki_pages
6
+ alias: tp
7
+ key: tp.id
8
+ to_s: [tp.long_title, tp.title]
9
+ order:
10
+ by:
11
+ tp.parent_id: asc
12
+ tp.order: asc
13
+ reorder: tp.order
14
+ attributes:
15
+ parent: { type: Object, required: true }
16
+ children: { type: Collection }
17
+ title: { type: String, size: 45, required: true }
18
+ long_title: { type: String, default: ~ }
19
+ content: { type: Html, required: true }
20
+ controller: { type: Object, required: true }
21
+ route: { type: String, size: 45, required: true, default: '' }
22
+ default_route: { type: String, size: 45, required: true, default: '' }
23
+ use_default_route: { type: Boolean, default: false }
24
+ hidden: { type: Boolean, default: false }
25
+ relations:
26
+ parent:
27
+ class: Page
28
+ type: one-to-many
29
+ inverse: children
30
+ join:
31
+ alias: tpp
32
+ on:
33
+ tpp.id: tp.parent_id
34
+ controller:
35
+ class: Controller
36
+ type: one-to-many
37
+ inverse: pages
38
+ join:
39
+ alias: tc
40
+ on:
41
+ tc.id: tp.parent_id
42
+ list:
43
+ parent: ~
44
+ title: { link: true }
45
+ controller: ~
46
+ default_route: ~
47
+ use_default_route: ~
48
+ hidden: ~
metadata ADDED
@@ -0,0 +1,168 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tanuki
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 3
10
+ version: 0.1.3
11
+ platform: ruby
12
+ authors:
13
+ - Anatoly Ressin
14
+ - Dimitry Solovyov
15
+ autorequire:
16
+ bindir: bin
17
+ cert_chain: []
18
+
19
+ date: 2010-08-19 00:00:00 +03:00
20
+ default_executable:
21
+ dependencies:
22
+ - !ruby/object:Gem::Dependency
23
+ name: rack
24
+ prerelease: false
25
+ requirement: &id001 !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ">="
29
+ - !ruby/object:Gem::Version
30
+ hash: 15
31
+ segments:
32
+ - 1
33
+ - 0
34
+ version: "1.0"
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: escape_utils
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ hash: 17
46
+ segments:
47
+ - 0
48
+ - 1
49
+ - 5
50
+ version: 0.1.5
51
+ type: :runtime
52
+ version_requirements: *id002
53
+ - !ruby/object:Gem::Dependency
54
+ name: rake
55
+ prerelease: false
56
+ requirement: &id003 !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ hash: 49
62
+ segments:
63
+ - 0
64
+ - 8
65
+ - 7
66
+ version: 0.8.7
67
+ type: :development
68
+ version_requirements: *id003
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ prerelease: false
72
+ requirement: &id004 !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ hash: 27
78
+ segments:
79
+ - 1
80
+ - 3
81
+ - 0
82
+ version: 1.3.0
83
+ type: :development
84
+ version_requirements: *id004
85
+ description: Tanuki is an MVVM-inspired web framework that fancies idiomatic Ruby, DRY and extensibility by its design.
86
+ email: tanuki@dimituri.com
87
+ executables:
88
+ - tanuki
89
+ extensions: []
90
+
91
+ extra_rdoc_files: []
92
+
93
+ files:
94
+ - app/tanuki/controller/controller.rb
95
+ - app/tanuki/controller/default.thtml
96
+ - app/tanuki/controller/index.thtml
97
+ - app/tanuki/controller/link.thtml
98
+ - app/tanuki/object/object.rb
99
+ - app/tanuki/page/missing/default.thtml
100
+ - app/tanuki/page/missing/missing.rb
101
+ - app/user/page/index/default.thtml
102
+ - app/user/page/index/index.rb
103
+ - bin/tanuki
104
+ - lib/tanuki/application.rb
105
+ - lib/tanuki/argument/base.rb
106
+ - lib/tanuki/argument/integer.rb
107
+ - lib/tanuki/argument/integer_range.rb
108
+ - lib/tanuki/argument/string.rb
109
+ - lib/tanuki/argument.rb
110
+ - lib/tanuki/configurator.rb
111
+ - lib/tanuki/context.rb
112
+ - lib/tanuki/controller_behavior.rb
113
+ - lib/tanuki/i18n.rb
114
+ - lib/tanuki/launcher.rb
115
+ - lib/tanuki/loader.rb
116
+ - lib/tanuki/module_extensions.rb
117
+ - lib/tanuki/object_behavior.rb
118
+ - lib/tanuki/template_compiler.rb
119
+ - lib/tanuki/version.rb
120
+ - lib/tanuki.rb
121
+ - schema/tanuki/l10n/en/controller.yml
122
+ - schema/tanuki/l10n/en/page.yml
123
+ - schema/tanuki/l10n/ru/controller.yml
124
+ - schema/tanuki/l10n/ru/page.yml
125
+ - schema/tanuki/models/controller.yml
126
+ - schema/tanuki/models/page.yml
127
+ - LICENSE
128
+ - README.rdoc
129
+ has_rdoc: true
130
+ homepage: http://github.com/dimituri/tanuki
131
+ licenses: []
132
+
133
+ post_install_message:
134
+ rdoc_options: []
135
+
136
+ require_paths:
137
+ - lib
138
+ required_ruby_version: !ruby/object:Gem::Requirement
139
+ none: false
140
+ requirements:
141
+ - - ">="
142
+ - !ruby/object:Gem::Version
143
+ hash: 49
144
+ segments:
145
+ - 1
146
+ - 9
147
+ - 1
148
+ version: 1.9.1
149
+ required_rubygems_version: !ruby/object:Gem::Requirement
150
+ none: false
151
+ requirements:
152
+ - - ">="
153
+ - !ruby/object:Gem::Version
154
+ hash: 23
155
+ segments:
156
+ - 1
157
+ - 3
158
+ - 6
159
+ version: 1.3.6
160
+ requirements: []
161
+
162
+ rubyforge_project:
163
+ rubygems_version: 1.3.7
164
+ signing_key:
165
+ specification_version: 3
166
+ summary: Web framework with balls!
167
+ test_files: []
168
+