tzispa_rig 0.4.5 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -4,7 +4,6 @@ require 'forwardable'
4
4
  require 'fileutils'
5
5
  require 'tzispa/utils/string'
6
6
  require 'tzispa/utils/indenter'
7
- require 'tzispa/rig'
8
7
 
9
8
  module Tzispa
10
9
  module Rig
@@ -13,13 +12,13 @@ module Tzispa
13
12
 
14
13
  class ReadError < IOError; end
15
14
 
16
- class File
15
+ class TemplateBase
17
16
 
18
- attr_reader :file, :content, :modified
17
+ attr_reader :content
19
18
 
20
- def initialize(file)
21
- @file = file
22
- @loaded = false
19
+ def initialize
20
+ @content = nil
21
+ @loaded = true
23
22
  end
24
23
 
25
24
  def loaded?
@@ -27,33 +26,63 @@ module Tzispa
27
26
  end
28
27
 
29
28
  def modified?
30
- @modified != ::File.mtime(@file)
29
+ false
31
30
  end
32
31
 
33
32
  def exist?
34
- ::File.exist?(@file)
33
+ true
35
34
  end
36
35
 
37
36
  def load!
38
- begin
39
- raise NotFound.new("Template file '#{@file}' not found") unless exist?
40
- ::File.open(@file, 'r:UTF-8') { |f|
41
- @content = String.new
42
- @modified = f.mtime
43
- while line = f.gets
44
- @content << line
45
- end
46
- f.close
37
+ self
38
+ end
39
+
40
+ def parse!
41
+ self
42
+ end
43
+
44
+ def render(context, binder=nil)
45
+ ""
46
+ end
47
+
48
+ end
49
+
50
+ class File < TemplateBase
51
+
52
+ attr_reader :filename, :encoding
53
+
54
+ def initialize(name, encoding: 'UTF-8')
55
+ super()
56
+ @filename = name
57
+ @loaded = false
58
+ @encoding = encoding
59
+ end
60
+
61
+ def modified?
62
+ @modified && (@modified != ::File.mtime(filename))
63
+ end
64
+
65
+ def exist?
66
+ ::File.exist?(filename)
67
+ end
68
+
69
+ def load!
70
+ raise NotFound.new("Template file '#{filename}' not found") unless exist?
71
+ ::File.open(filename, "r:#{encoding}") { |f|
72
+ @content = String.new
73
+ @modified = f.mtime
74
+ f.each { |line|
75
+ @content << line
47
76
  }
48
77
  @loaded = true
49
- rescue Errno::ENOENT
50
- raise ReadError.new "Template file '#{@file}' could not be read"
51
- end
78
+ }
52
79
  self
80
+ rescue Errno::ENOENT
81
+ raise ReadError.new "Template file '#{@file}' could not be read"
53
82
  end
54
83
 
55
84
  def create(content=nil)
56
- ::File.open(@file, "w") { |f|
85
+ ::File.open(filename, "w:#{encoding}") { |f|
57
86
  f.puts content
58
87
  }
59
88
  end
@@ -67,39 +96,32 @@ module Tzispa
67
96
  using Tzispa::Utils
68
97
 
69
98
  BASIC_TYPES = [:layout, :block, :static].freeze
70
- DEFAULT_FORMAT = 'htm'.freeze
71
- RIG_EXTENSION = 'rig'.freeze
99
+ RIG_EXTENSION = 'rig'
72
100
 
73
- attr_reader :name, :type, :domain, :format, :params, :parser, :engine, :subdomain, :childrens
101
+ attr_reader :id, :name, :type, :domain, :parser, :subdomain, :childrens, :content_type
74
102
  def_delegators :@parser, :attribute_tags
75
103
 
76
- def initialize(name:, type:, domain: nil, parent: nil, format: nil, params: nil, engine: nil)
77
- subdom_name = name.downcase.split('.')
78
- @subdomain = subdom_name.first if subdom_name.length > 1
79
- @name = subdom_name.last
104
+ def initialize(name:, type:, domain:, content_type:, params: nil)
105
+ @id = name
106
+ name.downcase.split('@').tap { |sdn|
107
+ @subdomain = sdn.length > 1 ? sdn.first : nil
108
+ @name = sdn.last
109
+ }
110
+ @domain = domain
111
+ @content_type = content_type
80
112
  @params = Parameters.new(params)
81
- @childrens = Array.new
82
113
  send('type=', type)
83
- if parent
84
- @engine = engine || parent.engine
85
- @domain = domain || parent.domain
86
- @format = format || parent.format
87
- else
88
- @engine = engine
89
- @domain = domain
90
- @format = format || DEFAULT_FORMAT
91
- end
92
- super "#{path}/#{@name}.#{RIG_EXTENSION}.#{@format}"
114
+ super "#{path}/#{@name}.#{RIG_EXTENSION}.#{content_type}"
93
115
  end
94
116
 
95
117
  def parse!
96
- @parser = ParserNext.new self
97
- @parser.parse!
118
+ @parser = ParserNext.new self, domain: domain, content_type: content_type, bindable: bindable?
119
+ parser.parse!
98
120
  self
99
121
  end
100
122
 
101
123
  def modified?
102
- super || (childrens.count > 0 && childrens.index { |tpl|
124
+ super || (parser && parser.childrens.index { |tpl|
103
125
  tpl.modified?
104
126
  })
105
127
  end
@@ -108,15 +130,15 @@ module Tzispa
108
130
  !content.empty? && !parser.empty?
109
131
  end
110
132
 
111
- def render(context)
112
- parse! unless @parser
113
- binder = TemplateBinder.for self, context
114
- binder.bind! if binder && binder.respond_to?(:bind!)
115
- @parser.render binder, context
133
+ def render(context, binder=nil)
134
+ parse! unless parser
135
+ binder ||= TemplateBinder.for self, context
136
+ binder.bind! if binder&.respond_to?(:bind!)
137
+ parser.render binder
116
138
  end
117
139
 
118
140
  def path
119
- "#{@domain.path}/rig/#{@type.to_s.downcase}#{'/'+@subdomain if @subdomain}"
141
+ @path ||= "#{domain.path}/view/#{subdomain || '_'}/#{type.to_s.downcase}"
120
142
  end
121
143
 
122
144
  def create(content='')
@@ -150,20 +172,22 @@ module Tzispa
150
172
  end
151
173
 
152
174
  def binder_require
153
- "rig/#{@type}/#{@subdomain+'/' if @subdomain}#{@name.downcase}"
175
+ @binder_require ||= "view/#{subdomain || '_'}/#{type}/#{name.downcase}"
154
176
  end
155
177
 
156
178
  def binder_namespace
157
- "#{@domain.name.to_s.camelize}::Rig::#{@type.to_s.capitalize}#{'::' + @subdomain.camelize if @subdomain}"
179
+ @binder_namespace ||= "#{domain.name.to_s.camelize}::#{subdomain&.camelize}View"
158
180
  end
159
181
 
160
182
  def binder_class_name
161
- @name.camelize
183
+ @binder_class_name ||= @name.camelize
162
184
  end
163
185
 
164
186
  def binder_class
165
- @domain.require binder_require
166
- "#{binder_namespace}::#{binder_class_name}".constantize
187
+ @binder_class ||= begin
188
+ domain.require binder_require
189
+ "#{binder_namespace}::#{binder_class_name}#{type.to_s.capitalize}".constantize
190
+ end
167
191
  end
168
192
 
169
193
  private
@@ -176,7 +200,7 @@ module Tzispa
176
200
  def create_binder
177
201
  ::File.open("#{domain.path}/#{binder_require}.rb", "w") { |f|
178
202
  f.puts write_binder_code
179
- } if @type == :block
203
+ } if type == :block
180
204
  end
181
205
 
182
206
  def write_binder_code
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'forwardable'
4
+
5
+ module Tzispa
6
+ module Rig
7
+
8
+ class Token
9
+ extend Forwardable
10
+
11
+ RE_ANCHOR = /(\$\$\h+\$\$)/
12
+
13
+ attr_reader :type, :parser
14
+ def_delegators :@parser, :domain, :content_type, :template
15
+
16
+ def initialize(parser, type)
17
+ @parser = parser
18
+ @type = type
19
+ end
20
+
21
+ def self.instance(parser, type, match)
22
+ case type
23
+ when :meta
24
+ TypeToken::Meta.new parser, type, match[1]
25
+ when :var
26
+ TypeToken::Var.new parser, type, match[1], match[2]
27
+ when :url
28
+ TypeToken::Url.new parser, match[1].to_sym, match[3], match[5], match[2]&.slice(1..-1)
29
+ when :api
30
+ TypeToken::Api.new parser, match[1].to_sym, match[3], match[4], match[5], match[6], match[2]&.slice(1..-1)
31
+ when :loop
32
+ TypeToken::Loop.new parser, type, match[3], match[4]
33
+ when :ife
34
+ TypeToken::Ife.new parser, type, match[7], match[8], match[10]
35
+ when :blk
36
+ TypeToken::Block.new parser, type, match[3], match[4]
37
+ when :iblk
38
+ TypeToken::IBlock.new parser, type, match[7], match[8], match[9], match[10], match[11]
39
+ when :static
40
+ TypeToken::Static.new parser, type, match[14], match[15]
41
+ end
42
+ end
43
+
44
+ def anchor
45
+ @anchor ||= "$$#{"%x" % object_id}$$".freeze
46
+ end
47
+
48
+ end
49
+
50
+ require 'tzispa/rig/type_token/api_url'
51
+ require 'tzispa/rig/type_token/expression'
52
+ require 'tzispa/rig/type_token/statement'
53
+ require 'tzispa/rig/type_token/block'
54
+
55
+
56
+ end
57
+ end
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tzispa
4
+ module Rig
5
+ module TypeToken
6
+
7
+ class Url < Rig::Token
8
+
9
+ attr_reader :layout, :params, :app_name
10
+
11
+ def initialize(parser, type, layout, params, app_name = nil)
12
+ super(parser, type)
13
+ @layout = layout
14
+ @params = params
15
+ @app_name = app_name&.to_sym
16
+ end
17
+
18
+ def render(binder)
19
+ b_layout = bind_value(@layout.dup, binder).to_sym
20
+ h_params = Rig::Parameters.new(bind_value(@params&.dup, binder)).to_h
21
+ case type
22
+ when :purl
23
+ render_purl(binder, app_name, b_layout, h_params)
24
+ when :url
25
+ render_url(binder, app_name, b_layout, h_params)
26
+ end
27
+ end
28
+
29
+ def render_purl(binder, app_name, b_layout, h_params)
30
+ app_name ?
31
+ binder.context.app_layout_path(app_name, b_layout, h_params) :
32
+ binder.context.layout_path(b_layout, h_params)
33
+ end
34
+
35
+ def render_url(binder, app_name, b_layout, h_params)
36
+ app_name ?
37
+ binder.context.app_layout_canonical_url(app_name, b_layout, h_params) :
38
+ binder.context.layout_canonical_url(b_layout, h_params)
39
+ end
40
+
41
+ def bind_value(value, binder)
42
+ value&.gsub(RE_ANCHOR) { |match|
43
+ parser.tokens.select { |p| p.anchor == match}.first.render(binder)
44
+ }
45
+ end
46
+
47
+ end
48
+
49
+
50
+ class Api < Rig::Token
51
+
52
+ attr_reader :handler, :verb, :predicate, :app_name
53
+
54
+ def initialize(parser, type, handler, verb, predicate, sufix, app_name = nil)
55
+ super(parser, type)
56
+ @handler = handler
57
+ @verb = verb
58
+ @predicate = predicate
59
+ @sufix = sufix
60
+ @app_name = app_name&.to_sym
61
+ end
62
+
63
+ def render(binder)
64
+ b_handler = bind_value @handler.dup, binder
65
+ b_verb = bind_value @verb.dup, binder
66
+ b_predicate = bind_value( @predicate.dup, binder ) if @predicate
67
+ b_sufix = bind_value( @sufix.dup, binder ) if @sufix
68
+ binder.context.send(type.to_sym, b_handler, b_verb, b_predicate, b_sufix, app_name)
69
+ end
70
+
71
+ private
72
+
73
+ def bind_value(value, binder)
74
+ value.gsub(RE_ANCHOR) { |match|
75
+ parser.tokens.select { |p| p.anchor == match}.first.render(binder)
76
+ }
77
+ end
78
+
79
+ end
80
+
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,144 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tzispa
4
+ module Rig
5
+ module TypeToken
6
+
7
+ class Block < Rig::Token
8
+
9
+ attr_reader :id, :params
10
+
11
+ def initialize(parser, type, id, params)
12
+ super(parser, type)
13
+ @id = id
14
+ @params = params
15
+ end
16
+
17
+ def parse!
18
+ # to avoid infinite recursion
19
+ @parsed_block = obtain_block @id
20
+ parser.childrens << @parsed_block
21
+ self
22
+ end
23
+
24
+ def render(binder)
25
+ blk = @parsed_block.dup
26
+ blk.params = bind_value(@params.dup, binder) if @params
27
+ blk.render binder.context
28
+ end
29
+
30
+ private
31
+
32
+ def bind_value(value, binder)
33
+ value.gsub(RE_ANCHOR) { |match|
34
+ parser.tokens.select { |p| p.anchor == match}.first.render(binder)
35
+ }
36
+ end
37
+
38
+ def obtain_block(id)
39
+ case id
40
+ when '__empty__'
41
+ Rig::Engine.empty
42
+ when template&.id
43
+ # to avoid infinite recursion
44
+ template&.type == :block ?
45
+ template :
46
+ Rig::Engine.block(name: id, domain: domain, content_type: content_type)
47
+ else
48
+ Rig::Engine.block(name: id, domain: domain, content_type: content_type)
49
+ end
50
+ end
51
+
52
+
53
+ end
54
+
55
+
56
+ class IBlock < Rig::Token
57
+
58
+ attr_reader :id, :id_then, :params_then, :id_else, :params_else
59
+
60
+ def initialize(parser, type, test, id_then, params_then, id_else, params_else)
61
+ super(parser, type)
62
+ @id = test
63
+ @id_then = id_then
64
+ @params_then = params_then
65
+ @id_else = id_else
66
+ @params_else = params_else
67
+ end
68
+
69
+ def parse!
70
+ @block_then = obtain_block @id_then
71
+ @block_else = obtain_block @id_else
72
+ parser.childrens << @block_then << @block_else
73
+ self
74
+ end
75
+
76
+ def render(binder)
77
+ if binder.data.respond_to?(@id) && binder.data.send(@id)
78
+ blk = @block_then.dup
79
+ blk.params = bind_value(@params_then.dup, binder) if @params_then
80
+ else
81
+ blk = @block_else.dup
82
+ blk.params = bind_value(@params_else.dup, binder) if @params_else
83
+ end
84
+ blk.render binder.context
85
+ end
86
+
87
+ private
88
+
89
+ def obtain_block(id)
90
+ case id
91
+ when '__empty__'
92
+ Rig::Engine.empty
93
+ when template&.id
94
+ # to avoid infinite recursion
95
+ template&.type == :block ?
96
+ template :
97
+ Rig::Engine.block(name: id, domain: domain, content_type: content_type)
98
+ else
99
+ Rig::Engine.block(name: id, domain: domain, content_type: content_type)
100
+ end
101
+ end
102
+
103
+ def bind_value(value, binder)
104
+ value.gsub(RE_ANCHOR) { |match|
105
+ parser.tokens.select { |p| p.anchor == match}.first.render(binder)
106
+ }
107
+ end
108
+
109
+ end
110
+
111
+
112
+ class Static < Rig::Token
113
+
114
+ attr_reader :id, :params
115
+
116
+ def initialize(parser, type, id, params)
117
+ super(parser, type)
118
+ @id = id
119
+ @params = params
120
+ end
121
+
122
+ def parse!
123
+ @parsed_static = Tzispa::Rig::Engine.static name: @id, domain: domain, content_type: content_type
124
+ parser.childrens << @parsed_static
125
+ self
126
+ end
127
+
128
+ def render(binder)
129
+ blk = @parsed_static.dup
130
+ if @params
131
+ b_params = @params.dup.gsub(RE_ANCHOR) { |match|
132
+ parser.tokens.select { |p| p.anchor == match}.first.render(binder)
133
+ }
134
+ blk.params = b_params
135
+ end
136
+ blk.render binder.context
137
+ end
138
+
139
+ end
140
+
141
+
142
+ end
143
+ end
144
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'tzispa/utils/string'
4
+
5
+ module Tzispa
6
+ module Rig
7
+ module TypeToken
8
+
9
+ class Meta < Rig::Token
10
+
11
+ attr_reader :id
12
+
13
+ def initialize(parser, type, id)
14
+ super(parser, type)
15
+ @id = id.to_sym
16
+ end
17
+
18
+ def render(binder)
19
+ if binder.data.respond_to? @id
20
+ binder.data.send(@id).to_s
21
+ else
22
+ unknown
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ def unknown
29
+ @unknown ||= "#{@id}"
30
+ end
31
+
32
+ end
33
+
34
+
35
+ class Var < Rig::Token
36
+ using Tzispa::Utils
37
+
38
+ attr_reader :id
39
+
40
+ def initialize(parser, type, format, id)
41
+ super(parser, type)
42
+ @format = format
43
+ @id = id.to_sym
44
+ end
45
+
46
+ def render(binder)
47
+ if binder.data.respond_to?(@id)
48
+ value = binder.data.send(@id).to_s
49
+ value.send(parser.content_escape_method) rescue value
50
+ else
51
+ unknown
52
+ end
53
+ end
54
+
55
+ private
56
+
57
+ def unknown
58
+ @unknown ||= "#{@id}"
59
+ end
60
+
61
+ end
62
+
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'forwardable'
4
+
5
+ module Tzispa
6
+ module Rig
7
+ module TypeToken
8
+
9
+ class Loop < Rig::Token
10
+ extend Forwardable
11
+
12
+ attr_reader :id, :body_parser
13
+ def_delegators :@body_parser, :attribute_tags, :loop_parser
14
+
15
+ def initialize(parser, type, id, body)
16
+ super(parser, type)
17
+ @id = id.to_sym
18
+ @body = body
19
+ end
20
+
21
+ def parse!
22
+ @body_parser = Rig::ParserNext.new(template, text: @body, parent: parser, bindable: true ).parse!
23
+ self
24
+ end
25
+
26
+ def render(binder)
27
+ String.new.tap { |text|
28
+ looper = binder.data.send(@id) if binder.data.respond_to?(@id)
29
+ looper&.data&.each { |loop_item|
30
+ text << body_parser.render(loop_item) if loop_item
31
+ } if looper
32
+ }
33
+ end
34
+
35
+ end
36
+
37
+
38
+ class Ife < Rig::Token
39
+
40
+ attr_reader :test, :then_parser, :else_parser
41
+
42
+ def initialize(parser, type, test, then_body, else_body)
43
+ super(parser, type)
44
+ @test = test.to_sym
45
+ @then_body = then_body
46
+ @else_body = else_body
47
+ end
48
+
49
+ def parse!
50
+ @then_parser = Rig::ParserNext.new(template, text: @then_body, parent: parser ).parse!
51
+ @else_parser = @else_body ? Rig::ParserNext.new(template, text: @else_body, parent: parser ).parse! : nil
52
+ self
53
+ end
54
+
55
+ def attribute_tags
56
+ @attribute_tags ||= [test].concat(then_parser.attribute_tags).concat(else_parser&.attribute_tags || Array.new).compact.uniq.freeze
57
+ end
58
+
59
+ def loop_parser(id)
60
+ @then_parser.loop_parser(id).concat(else_parser&.loop_parser(id) || Array.new).compact.freeze
61
+ end
62
+
63
+ def render(binder)
64
+ test_eval = binder.data && binder.data.respond_to?(test) && binder.data.send(test)
65
+ ifeparser = test_eval ? then_parser : else_parser
66
+ ifeparser ? ifeparser.render(binder) : ''
67
+ end
68
+
69
+ end
70
+
71
+ end
72
+ end
73
+ end
@@ -3,7 +3,7 @@
3
3
  module Tzispa
4
4
  module Rig
5
5
 
6
- VERSION = '0.4.5'
6
+ VERSION = '0.5.0'
7
7
  GEM_NAME = 'tzispa_rig'
8
8
 
9
9
  end
data/lib/tzispa/rig.rb CHANGED
@@ -1,11 +1,12 @@
1
1
  module Tzispa
2
2
  module Rig
3
-
3
+
4
4
  require 'tzispa/rig/version'
5
5
  require 'tzispa/rig/parameters'
6
+ require 'tzispa/rig/token'
6
7
  require 'tzispa/rig/parsernext'
8
+ require 'tzispa/rig/template'
7
9
  require 'tzispa/rig/binder'
8
- require 'tzispa/rig/template'
9
10
  require 'tzispa/rig/engine'
10
11
 
11
12
  end