tzispa_rig 0.4.5 → 0.5.0

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.
@@ -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