mustache_render 0.0.7 → 0.0.9

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.
@@ -9,17 +9,43 @@ MustacheRender.configure do |config|
9
9
  config.file_template_root_path = "#{Rails.root}/app/templates"
10
10
 
11
11
  # 默认的文件模板的扩展名称
12
- config.file_template_extension = 'mustache'
12
+ config.file_template_extension = '.mustache'
13
13
 
14
- # 当模板缺少的时候是否抛出异常
14
+ # 默认的数据模板的扩展名称
15
+ config.db_template_extension = '.mustache'
16
+
17
+ # 当字段缺少的时候是否抛出异常
15
18
  config.raise_on_context_miss = false
16
19
 
20
+ # 当数据库模板不存在时候是否抛出异常
21
+ config.raise_on_db_template_miss = true
22
+
23
+ # 当文件模板不存在时候是否抛出异常
24
+ config.raise_on_file_template_miss = true
25
+
26
+ ### 模板的相关配置 ###########################
27
+ # 数据库模板是否需要缓存
28
+ config.db_template_cache = true
29
+ # 文件模板是否需要缓存
30
+ config.file_template_cache = false
31
+ # 数据库模板缓存过期时间
32
+ config.db_template_cache_expires_in = 1.hours
33
+ # 文件模板缓存的过期时间, 注意文件系统没有自动清理缓存的机制,建议设置的短一些
34
+ config.file_template_cache_expires_in = 1.minutes
35
+ # 缓存的媒介
36
+ config.cache_store = Rails.cache
37
+
38
+ # 版本适配器的配置
17
39
  config.adapter_configure do |adapter|
18
40
 
19
41
  end
20
42
 
43
+ # 管理中心是否需要登录
21
44
  config.manage_center_need_login = true
45
+ # 用户登录的url
22
46
  config.user_login_url = '/login'
47
+ # 管理员登录失败后跳往的URL
23
48
  config.manager_authenticate_fail_url = '/login'
49
+
24
50
  end
25
51
 
@@ -25,7 +25,7 @@ module MustacheRender
25
25
  # 默认的渲染媒介
26
26
  #
27
27
  def default_render_media
28
- @default_render_media ||= :db
28
+ @default_render_media ||= :file
29
29
  end
30
30
 
31
31
  def default_render_media= media
@@ -48,6 +48,69 @@ module MustacheRender
48
48
  @user_login_url ||= url
49
49
  end
50
50
 
51
+ def cache
52
+ return @_cache_store if defined?(@_cache_store)
53
+
54
+ @_cache_store ||= Rails.cache
55
+ # @_cache_store ||= MemCache.new('localhost:11211', :namespace => 'mustache_render#cache')
56
+ end
57
+
58
+ def cache_store= cache_store
59
+ @_cache_store ||= cache_store
60
+ end
61
+
62
+ #
63
+ # 是否开启缓存
64
+ #
65
+ def db_template_cache?
66
+ if defined?(@_db_template_cache)
67
+ @_db_template_cache
68
+ else
69
+ true
70
+ end
71
+ end
72
+
73
+ #
74
+ # 是否开启缓存
75
+ #
76
+ def file_template_cache?
77
+ if defined?(@_file_template_cache)
78
+ @_file_template_cache
79
+ else
80
+ false
81
+ end
82
+ end
83
+
84
+ #
85
+ # 设置是否启用缓存
86
+ #
87
+ def db_template_cache= user_cache
88
+ @_db_template_cache = user_cache unless defined?(@_db_template_cache)
89
+ end
90
+
91
+ #
92
+ # 设置是否启用缓存
93
+ #
94
+ def file_template_cache= user_cache
95
+ @_file_template_cache = user_cache unless defined?(@_file_template_cache)
96
+ end
97
+
98
+ def db_template_cache_expires_in
99
+ @db_template_cache_expires_in ||= 1.hours
100
+ end
101
+
102
+ def file_template_cache_expires_in
103
+ @file_template_cache_expires_in ||= 5.minutes
104
+ end
105
+
106
+ def db_template_cache_expires_in= expires_in
107
+ @db_template_cache_expires_in ||= expires_in
108
+ end
109
+
110
+ def file_template_cache_expires_in= expires_in
111
+ @file_template_cache_expires_in ||= expires_in
112
+ end
113
+
51
114
  def manage_center_need_login?
52
115
  if defined?(@manage_center_need_login)
53
116
  @manage_center_need_login
@@ -76,20 +139,46 @@ module MustacheRender
76
139
  @file_template_root_path ||= path
77
140
  end
78
141
 
142
+ def db_template_extension
143
+ @db_template_extension ||= '.mustache'
144
+ end
145
+
146
+ def db_template_extension= name
147
+ @db_template_extension ||= name
148
+ end
149
+
79
150
  def file_template_extension
80
- @file_template_extension ||= 'mustache'
151
+ @file_template_extension ||= '.mustache'
81
152
  end
82
153
 
83
154
  def file_template_extension= name
84
155
  @file_template_extension ||= name
85
156
  end
86
157
 
158
+ # 是否抛出文件模板丢失的异常?
159
+ def raise_on_file_template_miss= _bool
160
+ @raise_on_file_template_miss = _bool unless defined?(@raise_on_file_template_miss)
161
+ end
162
+
163
+ def raise_on_file_template_miss?
164
+ defined?(@raise_on_file_template_miss) ? @raise_on_file_template_miss : true
165
+ end
166
+
167
+ # 是否抛出数据库模板miss的异常
168
+ def raise_on_db_template_miss= _bool
169
+ @raise_on_db_template_miss = _bool unless defined?(@raise_on_db_template_miss)
170
+ end
171
+
172
+ def raise_on_db_template_miss?
173
+ defined?(@raise_on_db_template_miss) ? @raise_on_db_template_miss : true
174
+ end
175
+
87
176
  def raise_on_context_miss?
88
177
  defined?(@raise_on_context_miss) ? @raise_on_context_miss : false
89
178
  end
90
179
 
91
- def raise_on_context_miss=(boolean)
92
- @raise_on_context_miss = boolean
180
+ def raise_on_context_miss=(_bool)
181
+ @raise_on_context_miss = _bool unless defined?(@raise_on_context_miss)
93
182
  end
94
183
 
95
184
  def manage_view_base
@@ -20,11 +20,16 @@ module MustacheRender::Models
20
20
  validates_presence_of :folder_id
21
21
  validates_presence_of :name
22
22
  validates_presence_of :change_log, :if => Proc.new { |r| !(r.new_record?) }
23
+ validates_uniqueness_of :name, :scope => [:folder_id, :name]
23
24
 
24
25
  validate do |r|
25
26
  r.errors.add :change, '没有改动' if !(r.new_record?) && !(r.changed?)
26
27
  end
27
28
 
29
+ before_save do |r|
30
+ ::MustacheRender::Mustache.delete_partial_cache(r.full_path_was, :db)
31
+ end
32
+
28
33
  extend ClassMethods
29
34
  include InstanceMethods
30
35
  end
@@ -38,12 +43,27 @@ module MustacheRender::Models
38
43
  # 首先获取文件夹的名称, 然后获取文件名
39
44
  tmp_paths = name.to_s.split('/')
40
45
 
41
- template_name = tmp_paths.pop.to_s
46
+ template_name = ::MustacheRender::Mustache.generate_template_name(
47
+ tmp_paths.pop.to_s,
48
+ ::MustacheRender.config.db_template_extension
49
+ )
42
50
 
43
51
  folder_full_path = "#{tmp_paths.join('/')}"
52
+
53
+ # 需要以 / 开头,此处fix一下这里
54
+ unless folder_full_path.start_with?('/')
55
+ folder_full_path = "/#{folder_full_path}"
56
+ end
57
+
44
58
  folder = ::MustacheRenderFolder.find_by_full_path(folder_full_path)
45
59
 
46
- self.find_by_folder_id_and_name(folder.try(:id), template_name)
60
+ template = self.find_by_folder_id_and_name(folder.try(:id), template_name)
61
+
62
+ if ::MustacheRender.config.raise_on_db_template_miss? && template.nil?
63
+ raise ::MustacheRender::Mustache::TemplateMiss.new("read db template error: folder_full_path -> #{folder_full_path} template_name: #{template_name}")
64
+ end
65
+
66
+ template
47
67
  end
48
68
  end
49
69
 
@@ -19,18 +19,23 @@ module MustacheRender
19
19
  end
20
20
 
21
21
  def render(data = template, ctx = {})
22
- tpl = templateify(data)
23
-
24
- return tpl.render(context) if ctx == {}
22
+ self.template = data
23
+
24
+ return self.template.render(context) if ctx == {}
25
25
 
26
26
  begin
27
27
  context.push(ctx)
28
- tpl.render(context)
28
+ self.template.render(context)
29
29
  ensure
30
30
  context.pop
31
31
  end
32
32
  end
33
33
 
34
+ # 片段树
35
+ def partials_tree
36
+
37
+ end
38
+
34
39
  # Context accessors.
35
40
  #
36
41
  # view = Mustache.new
@@ -74,13 +79,68 @@ module MustacheRender
74
79
  render(partial(full_path), context)
75
80
  end
76
81
 
77
- def read_template_from_meida name
82
+ def impl_read_db_template name
83
+ db_template = ::MustacheRenderTemplate.find_with_full_path(name)
84
+ db_template.try :content
85
+ end
86
+
87
+ def self.generate_template_name(name, template_extension)
88
+ # 如果路径中以扩展名结尾,则直接去取这个文件
89
+ name = name.to_s.strip
90
+
91
+ if name.start_with?('/')
92
+ name = name[1..-1]
93
+ end
94
+
95
+ if name.end_with?(template_extension)
96
+ "#{name}"
97
+ else
98
+ "#{name}#{template_extension}"
99
+ end
100
+ end
101
+
102
+ def impl_read_file_template name
103
+ # TODO: 对路径的语法需要加强
104
+ full_path = "#{config.file_template_root_path}/#{self.class.generate_template_name(name, config.file_template_extension)}"
105
+ begin
106
+ File.read full_path
107
+ rescue
108
+ if config.raise_on_file_template_miss?
109
+ raise ::MustacheRender::Mustache::TemplateMiss.new("read file template error: #{full_path}")
110
+ else
111
+ ''
112
+ end
113
+ end
114
+ end
115
+
116
+ def read_template_from_media name, media
117
+ # puts "read_template_from_media: #{name} #{media}"
78
118
  case media
79
119
  when :db
80
- db_template = ::MustacheRenderTemplate.find_with_full_path(name)
81
- db_template.try :content
120
+ if ::MustacheRender.config.db_template_cache?
121
+ self.class.fetch_partial_cache name, media, :expires_in => ::MustacheRender.config.db_template_cache_expires_in do
122
+ impl_read_db_template name
123
+ end
124
+ else
125
+ impl_read_db_template name
126
+ end
82
127
  when :file
83
- File.read "#{config.file_template_root_path}/#{name}.#{config.file_template_extension}"
128
+ if ::MustacheRender.config.file_template_cache?
129
+ self.class.fetch_partial_cache name, media, :expires_in => ::MustacheRender.config.file_template_cache_expires_in do
130
+ impl_read_file_template name
131
+ end
132
+ else
133
+ impl_read_file_template name
134
+ end
135
+ end
136
+ end
137
+
138
+ def self.fix_path_name name
139
+ # 需要以 / 开头,此处fix一下这里
140
+ if name.to_s.start_with?('/')
141
+ name.to_s
142
+ else
143
+ "/#{name}"
84
144
  end
85
145
  end
86
146
 
@@ -88,7 +148,39 @@ module MustacheRender
88
148
  # reading templates from a database. It will be rendered by the
89
149
  # context, so all you need to do is return a string.
90
150
  def partial(name)
91
- self.read_template_from_meida name
151
+ name = self.class.fix_path_name name
152
+ # return self.read_template_from_media name, media
153
+ @_cached_partials ||= {}
154
+ (@_cached_partials[media] ||= {})[name] ||= self.read_template_from_media name, media
155
+ end
156
+
157
+ def self.partial_cache_key(name, media)
158
+ raise 'options key: :media must in(:file, :db)' unless [:file, :db].include?(media)
159
+ "MustacheRender::Mustache#Template.cache##{media}##{name}"
160
+ end
161
+
162
+ def self.exist_partial_cache?(name, media)
163
+ ::MustacheRender.config.cache.exist?(self.partial_cache_key(name, media))
164
+ end
165
+
166
+ def self.delete_partial_cache(name, media)
167
+ ::MustacheRender.config.cache.delete(self.partial_cache_key(name, media))
168
+ end
169
+
170
+ def self.fetch_partial_cache(name, media, options={}, &block)
171
+ ::MustacheRender.config.cache.fetch(self.partial_cache_key(name, media), options) do
172
+ if block_given?
173
+ block.call
174
+ end
175
+ end
176
+ end
177
+
178
+ def self.read_partial_cache(name, media)
179
+ ::MustacheRender.config.cache.read(self.partial_cache_key(name, media))
180
+ end
181
+
182
+ def self.write_partial_cache(name, media, value, options={})
183
+ ::MustacheRender.config.cache.write(self.partial_cache_key(name, media), value, options)
92
184
  end
93
185
 
94
186
  # Override this to provide custom escaping.
@@ -165,6 +257,16 @@ module MustacheRender
165
257
  (@template && @template.is_a?(Template)) || self.class.compiled?
166
258
  end
167
259
 
260
+ def template
261
+ return @template if @template
262
+
263
+ self.template = ''
264
+ end
265
+
266
+ def template= template
267
+ @template = templateify(template)
268
+ end
269
+
168
270
  # template_partial => TemplatePartial
169
271
  # template/partial => Template::Partial
170
272
  def self.classify(underscored)
@@ -39,7 +39,7 @@ module MustacheRender
39
39
  # Find the first Mustache in the stack. If we're being rendered
40
40
  # inside a Mustache object as a context, we'll use that one.
41
41
  def mustache_in_stack
42
- @stack.detect { |frame| frame.is_a?(Mustache) }
42
+ @stack.detect { |frame| frame.is_a?(::MustacheRender::Mustache) }
43
43
  end
44
44
 
45
45
  # Allows customization of how Mustache escapes things.
@@ -104,7 +104,7 @@ module MustacheRender
104
104
  end
105
105
  end
106
106
 
107
- if default == :__raise || MustacheRender.config.raise_on_context_miss?
107
+ if default == :__raise || ::MustacheRender.config.raise_on_context_miss?
108
108
  raise ContextMiss.new("Can't find #{name} in #{@stack.inspect}")
109
109
  else
110
110
  default
@@ -102,6 +102,10 @@ module MustacheRender
102
102
  error "Unclosed section #{type.inspect}", pos
103
103
  end
104
104
 
105
+ # puts ""
106
+ # puts "-----------------------------------------------------"
107
+ # puts @result
108
+
105
109
  @result
106
110
  end
107
111
 
@@ -6,6 +6,11 @@ require 'mustache_render/mustache/generator'
6
6
 
7
7
  module MustacheRender
8
8
  class Mustache
9
+ # 模板缺失
10
+ class TemplateMiss < ::RuntimeError
11
+
12
+ end
13
+
9
14
  # A Template represents a Mustache template. It compiles and caches
10
15
  # a raw string template into something usable.
11
16
  #
@@ -15,7 +20,7 @@ module MustacheRender
15
20
  #
16
21
  # You shouldn't use this class directly, instead:
17
22
  #
18
- # >> Mustache.render(template, hash)
23
+ # >> ::MustacheRender::Mustache.render(template, hash)
19
24
  class Template
20
25
  attr_reader :source
21
26
 
@@ -3,7 +3,7 @@ module MustacheRender
3
3
  VERSION_NUMBERS = [
4
4
  VERSION_MAJOR = 0,
5
5
  VERSION_MINOR = 0,
6
- VERSION_BUILD = 7,
6
+ VERSION_BUILD = 9,
7
7
  ]
8
8
 
9
9
  VERSION = VERSION_NUMBERS.join(".")
@@ -0,0 +1,67 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'MustacheRender::Mustache.db_render' do
4
+ before :each do
5
+ MustacheRender.configure do |config|
6
+ config.file_template_root_path = ROOT_PATH + '/resources/templates'
7
+ end
8
+ end
9
+
10
+ it 'template scan_tags test' do
11
+ result = MustacheRender::Mustache.file_render 'scan_tags/1', {}
12
+
13
+ end
14
+
15
+ it 'template file 5.mustache render ok' do
16
+ result = MustacheRender::Mustache.file_render 'basic/5', {}
17
+ result.should == <<-TEXT
18
+ file:5, in-file6
19
+
20
+ file:5-2, in-file6
21
+
22
+ file:5-3, in-file6
23
+
24
+ file:5-4, in-file6
25
+
26
+ file:5-5, in-file6
27
+
28
+ file:5-6, in-file6
29
+
30
+ file:5-7, in-file6
31
+
32
+ file:5-8, in-file6
33
+
34
+ file:5-9, in-file6
35
+
36
+ file:5-10, in-file6
37
+
38
+ file:5-11, in-file6
39
+
40
+ TEXT
41
+ end
42
+
43
+ it 'template file 1.mustache render ok' do
44
+ result = MustacheRender::Mustache.file_render 'basic/1', {:filename => '1.mustache'}
45
+ result.should == <<-TEXT
46
+ Hello!1.mustache
47
+ TEXT
48
+ end
49
+
50
+ it 'template 2 with partial 1 render OK' do
51
+ result = MustacheRender::Mustache.file_render 'basic/2', {:filename => 'in1'}
52
+ result.should == <<-TEXT
53
+ file-2Hello!in1
54
+
55
+ TEXT
56
+ end
57
+
58
+ it 'template file 3.mustache partial with 2 render OK' do
59
+ result = MustacheRender::Mustache.file_render 'basic/3', {:filename => 'in1'}
60
+ result.should == <<-TEXT
61
+ file3file-2Hello!in1
62
+
63
+
64
+ TEXT
65
+
66
+ end
67
+ end
@@ -0,0 +1 @@
1
+ Hello!{{filename}}
@@ -0,0 +1 @@
1
+ file-2{{>basic/1}}
@@ -0,0 +1 @@
1
+ file3{{>basic/2}}
@@ -0,0 +1 @@
1
+ file4{{>basic/3}}
@@ -0,0 +1,11 @@
1
+ file:5, {{>basic/6}}
2
+ file:5-2, {{>basic/6}}
3
+ file:5-3, {{>basic/6}}
4
+ file:5-4, {{>basic/6}}
5
+ file:5-5, {{>basic/6}}
6
+ file:5-6, {{>basic/6}}
7
+ file:5-7, {{>basic/6}}
8
+ file:5-8, {{>basic/6}}
9
+ file:5-9, {{>basic/7}}
10
+ file:5-10, {{>basic/7}}
11
+ file:5-11, {{>basic/7}}
@@ -0,0 +1 @@
1
+ {{>/basic/6}}
@@ -0,0 +1,2 @@
1
+ {{>/scan_tags/2}}
2
+ {{>/scan_tags/3}}
@@ -0,0 +1 @@
1
+ {{>/scan_tags/3}}
@@ -0,0 +1,3 @@
1
+ require 'mustache_render'
2
+
3
+ ROOT_PATH = File.dirname(__FILE__) + '/lib'
metadata CHANGED
@@ -1,61 +1,55 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: mustache_render
3
- version: !ruby/object:Gem::Version
4
- hash: 17
5
- prerelease: false
6
- segments:
7
- - 0
8
- - 0
9
- - 7
10
- version: 0.0.7
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.9
5
+ prerelease:
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - happy
14
9
  autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
-
18
- date: 2013-01-13 00:00:00 +08:00
19
- default_executable:
20
- dependencies:
21
- - !ruby/object:Gem::Dependency
12
+ date: 2013-01-21 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
22
15
  name: awesome_nested_set
23
- prerelease: false
24
- requirement: &id001 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
25
17
  none: false
26
- requirements:
27
- - - ">="
28
- - !ruby/object:Gem::Version
29
- hash: 3
30
- segments:
31
- - 0
32
- version: "0"
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
33
22
  type: :runtime
34
- version_requirements: *id001
35
- - !ruby/object:Gem::Dependency
36
- name: sqlite3
37
23
  prerelease: false
38
- requirement: &id002 !ruby/object:Gem::Requirement
24
+ version_requirements: !ruby/object:Gem::Requirement
39
25
  none: false
40
- requirements:
41
- - - ">="
42
- - !ruby/object:Gem::Version
43
- hash: 3
44
- segments:
45
- - 0
46
- version: "0"
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: sqlite3
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
47
38
  type: :development
48
- version_requirements: *id002
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
49
46
  description: Description of MustacheRender.
50
- email:
47
+ email:
51
48
  - andywang7259@gmail.com
52
49
  executables: []
53
-
54
50
  extensions: []
55
-
56
51
  extra_rdoc_files: []
57
-
58
- files:
52
+ files:
59
53
  - lib/mustache_render.rb
60
54
  - lib/tasks/mustache_render_tasks.rake
61
55
  - lib/generators/mustache_render/install_generator.rb
@@ -110,42 +104,43 @@ files:
110
104
  - lib/mustache_render/views/mustache_render/manage/folders/_new_2.html.erb
111
105
  - lib/mustache_render/views/mustache_render/manage/folders/_edit_2.html.erb
112
106
  - lib/mustache_render/adapter.rb
107
+ - spec/lib/mustache/file_render_spec.rb
108
+ - spec/lib/resources/templates/basic/6.mustache
109
+ - spec/lib/resources/templates/basic/2.mustache
110
+ - spec/lib/resources/templates/basic/1.mustache
111
+ - spec/lib/resources/templates/basic/7.mustache
112
+ - spec/lib/resources/templates/basic/3.mustache
113
+ - spec/lib/resources/templates/basic/5.mustache
114
+ - spec/lib/resources/templates/basic/4.mustache
115
+ - spec/lib/resources/templates/scan_tags/2.mustache
116
+ - spec/lib/resources/templates/scan_tags/1.mustache
117
+ - spec/lib/resources/templates/scan_tags/3.mustache
118
+ - spec/spec_helper.rb
113
119
  - MIT-LICENSE
114
120
  - Rakefile
115
121
  - README.rdoc
116
- has_rdoc: true
117
122
  homepage: http://blogsoso.net/
118
123
  licenses: []
119
-
120
124
  post_install_message:
121
125
  rdoc_options: []
122
-
123
- require_paths:
126
+ require_paths:
124
127
  - lib
125
- required_ruby_version: !ruby/object:Gem::Requirement
128
+ required_ruby_version: !ruby/object:Gem::Requirement
126
129
  none: false
127
- requirements:
128
- - - ">="
129
- - !ruby/object:Gem::Version
130
- hash: 3
131
- segments:
132
- - 0
133
- version: "0"
134
- required_rubygems_version: !ruby/object:Gem::Requirement
130
+ requirements:
131
+ - - ! '>='
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ required_rubygems_version: !ruby/object:Gem::Requirement
135
135
  none: false
136
- requirements:
137
- - - ">="
138
- - !ruby/object:Gem::Version
139
- hash: 3
140
- segments:
141
- - 0
142
- version: "0"
136
+ requirements:
137
+ - - ! '>='
138
+ - !ruby/object:Gem::Version
139
+ version: '0'
143
140
  requirements: []
144
-
145
141
  rubyforge_project:
146
- rubygems_version: 1.3.7
142
+ rubygems_version: 1.8.24
147
143
  signing_key:
148
144
  specification_version: 3
149
145
  summary: Summary of MustacheRender.
150
146
  test_files: []
151
-