octopress-hooks 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 8146d664fb709b511c92e4ae185dcc904896b395
4
+ data.tar.gz: 0842bc67f1fafbf5f853c9bc88a5a79ae91f6312
5
+ SHA512:
6
+ metadata.gz: df5cdfe5412c3a0e089b3d2d30f332283a8554477c0a0be790cb2dbc88466fd2e44963b398d66bd5e77b07689b79afb2d704cb4d3f31fcbdd192a02aad58d80b
7
+ data.tar.gz: 34191d047548eca5d6a081be03b59e9351450ba59b53872ceae5a08d7a45f0ed43fca2a47c883e895140d1e6942616e61c1344fb7908a474ecac57b1b336f15f
data/.gitignore ADDED
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ .DS_Store
19
+ _site
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0.0
4
+ - 1.9.3
5
+ script: cd test && bundle exec clash
6
+
data/CHANGELOG.md ADDED
@@ -0,0 +1,32 @@
1
+ # Changelog
2
+
3
+ ### 2.0.0
4
+ - Added support for Site hooks: pre_render, post_write and a way to patch the site payload.
5
+ - Changed name to octopress-hooks and moved repository to octopress/hooks.
6
+
7
+ ### 1.3.1
8
+ - No longer requires Octopress Ink.
9
+ - Renamed to octopress-hooks
10
+ - moved to https://github.com/octopress/hooks
11
+
12
+ ### 1.3.0
13
+ - Added support for processing partials as a ConvertiblePartial.
14
+
15
+ ### 1.2.0
16
+ - Added support Jekyll 2.0
17
+
18
+ ### 1.1.1
19
+ - Added support for Octopress Ink.
20
+
21
+ ### 1.1.0
22
+ - Added Jekyll::ConvertiblePage type to hookable classes.
23
+
24
+ ### 1.0.2
25
+ - Now requires Jekyll (oops).
26
+ - Added tests.
27
+
28
+ ### 1.0.1
29
+ - Naming refactor.
30
+
31
+ ### 1.0.0
32
+ - Initial release.
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in octopress-hooks.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Brandon Mathis
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,109 @@
1
+ # Octopress Hooks
2
+
3
+ This plugin isn't useful on its own. It monkeypatches Jekyll's Site, Post, Page and Convertible classes to allow plugin authors to access page and post data before and after render, and after write.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'octopress-hooks'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install octopress-hooks
18
+
19
+ ## Usage
20
+
21
+ First require this plugin at the top of a plugin file, inside of Jekyll's plugin directory. Then if your plugin class inherits the PageHooks class, the methods, `pre_render`, `post_render`, `post_write` will execute automatically in turn.
22
+
23
+ Here's an example.
24
+
25
+ ```ruby
26
+ require 'octopress-hooks'
27
+
28
+ class YourPageHooks < Octopress::Hooks::Page
29
+
30
+ # Manipulate page/post data before it has been processed with Liquid or
31
+ # Converters like Markdown or Textile.
32
+ #
33
+ def pre_render(page)
34
+ page.content = highlight_code(page.content)
35
+ end
36
+
37
+ # Manipulate page/post data after content has been processed to html.
38
+ #
39
+ def post_render(page)
40
+ page.content = link_headings(page.content)
41
+ end
42
+
43
+ # Access page/post data after it has been succesfully written to disk.
44
+ #
45
+ def post_write(page)
46
+ log_something(page.title)
47
+ end
48
+
49
+ end
50
+
51
+ class YourSiteHooks < Octopress::Hooks::Site
52
+
53
+ # Get access to the site before the render process
54
+ #
55
+ def pre_render(site)
56
+ # do something interesting
57
+ end
58
+
59
+ # Return a hash to be merged into the site payload
60
+ #
61
+ def merge_payload(payload, site)
62
+ { 'awesome' => true }
63
+ end
64
+
65
+ # Trigger some action after the site has been written
66
+ #
67
+ def post_write(site)
68
+ # do something interesting
69
+ end
70
+
71
+ end
72
+ ```
73
+
74
+ For a more complete example, check out [test.rb](test/_plugins/test.rb).
75
+
76
+ ### When to use what
77
+
78
+ #### For posts/pages
79
+
80
+ With `pre_render` you can access page and post data before it has been
81
+ processed by Liquid, Markdown, Textile, etc. You might want to do this if your
82
+ plugin requires text which conflicts with some content convertors. This way
83
+ you can replace that content with the correctly generated HTML before Liquid
84
+ or other convertors sees it.
85
+
86
+ With `post_render` you can access pages and posts after it has been proccessed into HTML. You might use this option if you want to modify generated HTML, for example adding anchors for each heading element.
87
+
88
+ With `post_write` you can execute a code block after a page or post has been
89
+ successfully written to disk. You might use this for logging or triggering
90
+ some external process.
91
+
92
+ #### For site
93
+
94
+ Use the `pre_render` hook to get access to the site class and modify it as necessary before posts and pages are rendered.
95
+ You could use this to modify these objects or even add to them.
96
+
97
+ Use the `merge_paylod` hook to add data that all documents will have access to when they are rendered, or modify the contents
98
+ of the site payload. Be sure to return a hash that can be merged.
99
+
100
+ Use the `post_write` to trigger and action after all documents have been written. With this you could gzip assets, or trigger a shell command.
101
+
102
+ ## Contributing
103
+
104
+ 1. Fork it ( https://github.com/octopress/hooks/fork )
105
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
106
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
107
+ 4. Push to the branch (`git push origin my-new-feature`)
108
+ 5. Create a new Pull Request
109
+
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,259 @@
1
+ require 'octopress-hooks/version'
2
+ require 'jekyll'
3
+
4
+ module Octopress
5
+ module Hooks
6
+
7
+ # Extended plugin type that allows the plugin
8
+ # to be called on varous callback methods.
9
+ #
10
+ class Page < Jekyll::Plugin
11
+
12
+ # Called before post is sent to the converter. Allows
13
+ # you to modify the post object before the converter
14
+ # does it's thing
15
+ #
16
+ def pre_render(post)
17
+ end
18
+
19
+ # Called after the post is rendered with the converter.
20
+ # Use the post object to modify it's contents before the
21
+ # post is inserted into the template.
22
+ #
23
+ def post_render(post)
24
+ end
25
+
26
+ # Called after the post is written to the disk.
27
+ # Use the post object to read it's contents to do something
28
+ # after the post is safely written.
29
+ #
30
+ def post_write(post)
31
+ end
32
+ end
33
+
34
+ class Site < Jekyll::Plugin
35
+
36
+ # Called before Jekyll renders posts and pages
37
+ # Returns nothing
38
+ #
39
+ def pre_render(site)
40
+ end
41
+
42
+ # Merges hash into site_payload
43
+ # Returns hash to be merged
44
+ #
45
+ def merge_payload(payload, site)
46
+ payload
47
+ end
48
+
49
+ # Called after Jekyll writes site files
50
+ # Returns nothing
51
+ #
52
+ def post_write(site)
53
+ end
54
+
55
+ end
56
+ end
57
+ end
58
+
59
+ # Monkey-patch Jekyll to add triggers for hooks
60
+
61
+ module Jekyll
62
+
63
+ # For compatibilty with old jekyll-page-hooks gem
64
+ #
65
+ class PageHooks < Octopress::Hooks::Page; end
66
+
67
+ # Monkey patch for the Jekyll Site class.
68
+ class Site
69
+
70
+ # Instance variable to store the various page_hook
71
+ # plugins that are loaded.
72
+ attr_accessor :page_hooks, :site_hooks
73
+
74
+ # Instantiates all of the hook plugins. This is basically
75
+ # a duplication of the other loaders in Site#setup.
76
+ def load_hooks
77
+ self.site_hooks = instantiate_subclasses(Octopress::Hooks::Site)
78
+ self.page_hooks = instantiate_subclasses(Octopress::Hooks::Page)
79
+ end
80
+
81
+
82
+ alias_method :old_site_payload, :site_payload
83
+ alias_method :old_render, :render
84
+ alias_method :old_write, :write
85
+
86
+ # Allows site hooks to get access to the site before
87
+ # the render method is called
88
+ #
89
+ # Returns nothing
90
+ def render
91
+ self.load_hooks
92
+
93
+ if self.site_hooks
94
+ self.site_hooks.each do |hook|
95
+ hook.pre_render(self)
96
+ end
97
+ end
98
+
99
+ old_render
100
+ end
101
+
102
+ # Allows site hooks to merge data into the site payload
103
+ #
104
+ # Returns the patched site payload
105
+ def site_payload
106
+ unless @cached_payload
107
+ payload = old_site_payload
108
+
109
+ if self.site_hooks
110
+ self.site_hooks.each do |hook|
111
+ p = hook.merge_payload(payload, self) || {}
112
+ if p != {}
113
+ payload = Jekyll::Utils.deep_merge_hashes(payload, p)
114
+ end
115
+ end
116
+ end
117
+
118
+ @cached_payload = payload
119
+ end
120
+
121
+ @cached_payload
122
+ end
123
+
124
+ # Trigger site hooks after site has been written
125
+ #
126
+ # Returns nothing
127
+ def write
128
+ old_write
129
+
130
+ if self.site_hooks
131
+ self.site_hooks.each do |hook|
132
+ hook.post_write(self)
133
+ end
134
+ end
135
+ end
136
+
137
+ end
138
+
139
+
140
+ # Create a new page class to allow partials to trigger Jekyll Page Hooks.
141
+ #
142
+ class ConvertiblePartial
143
+ include Convertible
144
+
145
+ attr_accessor :name, :content, :site, :ext, :output, :data
146
+
147
+ def initialize(site, name, content)
148
+ @site = site
149
+ @name = name
150
+ @ext = File.extname(name)
151
+ @content = content
152
+ @data = { layout: "no_layout" } # hack
153
+
154
+ end
155
+
156
+ def render(payload)
157
+ do_layout(payload, { no_layout: nil })
158
+ end
159
+ end
160
+
161
+ # Monkey patch for the Jekyll Convertible module.
162
+ module Convertible
163
+
164
+ def is_post?
165
+ self.is_a? Jekyll::Post
166
+ end
167
+
168
+ def is_page?
169
+ self.is_a? Jekyll::Page ||
170
+ self.class.to_s == 'Octopress::Ink::Page'
171
+ end
172
+
173
+ def is_convertible_partial?
174
+ self.is_a? Jekyll::ConvertiblePartial
175
+ end
176
+
177
+ def is_filterable?
178
+ is_post? or is_page? or is_convertible_partial?
179
+ end
180
+
181
+ # Call the #pre_render methods on all of the loaded
182
+ # page_hook plugins.
183
+ #
184
+ # Returns nothing
185
+ def pre_render
186
+ if self.site.page_hooks and is_filterable?
187
+ self.site.page_hooks.each do |filter|
188
+ filter.pre_render(self)
189
+ end
190
+ end
191
+ end
192
+
193
+ # Call the #post_render methods on all of the loaded
194
+ # page_hook plugins.
195
+ #
196
+ # Returns nothing
197
+ def post_render
198
+ if self.site.page_hooks and is_filterable?
199
+ self.site.page_hooks.each do |filter|
200
+ filter.post_render(self)
201
+ end
202
+ end
203
+ end
204
+
205
+ # Call the #post_write methods on all of the loaded
206
+ # page_hook plugins.
207
+ #
208
+ # Returns nothing
209
+ def post_write
210
+ if self.site.page_hooks and is_filterable?
211
+ self.site.page_hooks.each do |filter|
212
+ filter.post_write(self)
213
+ end
214
+ end
215
+ end
216
+
217
+ alias_method :old_transform, :transform
218
+ alias_method :old_do_layout, :do_layout
219
+ alias_method :old_write, :write
220
+
221
+ # Transform the contents based on the content type. Then calls the
222
+ # #post_render method if it exists
223
+ #
224
+ # Returns nothing.
225
+ def transform
226
+ old_transform
227
+ post_render if respond_to?(:post_render)
228
+ end
229
+
230
+ # Calls the pre_render method if it exists and then adds any necessary
231
+ # layouts to this convertible document.
232
+ #
233
+ # payload - The site payload Hash.
234
+ # layouts - A Hash of {"name" => "layout"}.
235
+ #
236
+ # Returns nothing.
237
+ def do_layout(payload, layouts)
238
+ pre_render if respond_to?(:pre_render)
239
+ old_do_layout(payload, layouts)
240
+ end
241
+
242
+ # Write the generated post file to the destination directory. It
243
+ # then calls any post_write methods that may exist.
244
+ # +dest+ is the String path to the destination dir
245
+ #
246
+ # Returns nothing
247
+ def write(dest)
248
+ old_write(dest)
249
+ post_write if respond_to?(:post_write)
250
+ end
251
+
252
+ # Returns the full url of the post, including the configured url
253
+ #
254
+ def full_url
255
+ self.site.config['url'] + self.url
256
+ end
257
+ end
258
+ end
259
+
@@ -0,0 +1,5 @@
1
+ module Octopress
2
+ module Hooks
3
+ VERSION = "2.0.0"
4
+ end
5
+ end
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'octopress-hooks/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "octopress-hooks"
8
+ gem.version = Octopress::Hooks::VERSION
9
+ gem.authors = ["Brandon Mathis"]
10
+ gem.email = ["brandon@imathis.com"]
11
+ gem.description = %q{Allows access to Jekyll's site, posts and pages at different points in the life cycle of a build. Formerly known as 'jekyll-page-hooks'.}
12
+ gem.summary = %q{Allows access to Jekyll's site, posts and pages at different points in the life cycle of a build. Formerly known as 'jekyll-page-hooks'.}
13
+ gem.homepage = "http://github.com/octopress/hooks"
14
+ gem.license = "MIT"
15
+
16
+ gem.add_runtime_dependency 'jekyll', '~> 2.0'
17
+
18
+ gem.add_development_dependency 'clash', '~> 1.0'
19
+
20
+ gem.files = `git ls-files`.split($/)
21
+ gem.require_paths = ["lib"]
22
+ end
data/test/.clash.yml ADDED
@@ -0,0 +1,2 @@
1
+ build: true
2
+ compare: _expected _site
data/test/.gitignore ADDED
@@ -0,0 +1 @@
1
+ _site
data/test/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'octopress-hooks', :path => '../'
4
+ gem 'pry-debugger'
5
+ gem 'clash'
6
+
data/test/_config.yml ADDED
@@ -0,0 +1,5 @@
1
+ title: Your New Jekyll Site
2
+ markdown: redcarpet
3
+ highlighter: pygments
4
+ exclude:
5
+ - Gemfile*
@@ -0,0 +1 @@
1
+ BOOM
@@ -0,0 +1 @@
1
+ MAGIC
@@ -0,0 +1 @@
1
+ <p>Your New Jekyll Site == Your New Jekyll Site</p>
@@ -0,0 +1 @@
1
+ <p><code>&lt;strong&gt;</code> is for the weak. The age of <code>&lt;blink&gt;&lt;strong&gt;</code> is <blink><strong>upon us</strong></blink>.</p>
@@ -0,0 +1 @@
1
+ <p>This page has been written</p>
@@ -0,0 +1 @@
1
+ <p>Snatch this _______ from my hand.</p>
@@ -0,0 +1,69 @@
1
+ require 'octopress-hooks'
2
+
3
+ module TestingHooks
4
+ class SiteHookTest < Octopress::Hooks::Site
5
+ def pre_render(site)
6
+ file = File.join(site.source, 'magic')
7
+ File.open(file, 'w') { |f| f.write('MAGIC') }
8
+ site.static_files << Jekyll::StaticFile.new(site, site.source, '', 'magic')
9
+ end
10
+
11
+ def merge_payload(payload, site)
12
+ if payload['site']['title']
13
+ payload['site']['name'] ||= payload['site']['title']
14
+ end
15
+
16
+ payload
17
+ end
18
+
19
+ def post_write(site)
20
+ file = File.join(site.config['destination'], 'boom')
21
+ File.open(file, 'w') { |f| f.write('BOOM') }
22
+ FileUtils.rm('magic')
23
+ end
24
+ end
25
+
26
+ class PageHooksTest < Jekyll::PageHooks
27
+
28
+ # Inherited methods from PageHooks
29
+
30
+ # Called before processors
31
+ #
32
+ def pre_render(page)
33
+ page.content = snatch_cupcake page.content
34
+ end
35
+
36
+ # Called after processors
37
+ #
38
+ def post_render(page)
39
+ page.content = blink_strong page.content
40
+ end
41
+
42
+ # Called after write
43
+ #
44
+ def post_write(page)
45
+ file = page.destination(page.site.config['destination'])
46
+ File.open(file, 'w') { |f| f.write(log_write(page.content)) }
47
+ end
48
+
49
+ # Plugin methods
50
+
51
+ # Replaces *cupcake* with _______ before markdown renders <em>cupcake</em>.
52
+ #
53
+ def snatch_cupcake(content)
54
+ content.sub /\*cupcake\*/, '_______'
55
+ end
56
+
57
+ def log_write(content)
58
+ content.sub /hasn&#39;t/, 'has'
59
+ end
60
+
61
+ # Replaces <strong> tag with <strong><blink> after html has been rendered.
62
+ #
63
+ def blink_strong(content)
64
+ content.gsub /(<strong>.+?<\/strong>)/ do
65
+ "<blink>#{$1}</blink>"
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,3 @@
1
+ ---
2
+ ---
3
+ {{ site.name }} == {{ site.title }}
@@ -0,0 +1,3 @@
1
+ ---
2
+ ---
3
+ `<strong>` is for the weak. The age of `<blink><strong>` is **upon us**.
@@ -0,0 +1,3 @@
1
+ ---
2
+ ---
3
+ This page hasn't been written
@@ -0,0 +1,3 @@
1
+ ---
2
+ ---
3
+ Snatch this *cupcake* from my hand.
metadata ADDED
@@ -0,0 +1,99 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: octopress-hooks
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Brandon Mathis
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-07-25 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: jekyll
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: clash
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.0'
41
+ description: Allows access to Jekyll's site, posts and pages at different points in
42
+ the life cycle of a build. Formerly known as 'jekyll-page-hooks'.
43
+ email:
44
+ - brandon@imathis.com
45
+ executables: []
46
+ extensions: []
47
+ extra_rdoc_files: []
48
+ files:
49
+ - ".gitignore"
50
+ - ".travis.yml"
51
+ - CHANGELOG.md
52
+ - Gemfile
53
+ - LICENSE.txt
54
+ - README.md
55
+ - Rakefile
56
+ - lib/octopress-hooks.rb
57
+ - lib/octopress-hooks/version.rb
58
+ - octopress-hooks.gemspec
59
+ - test/.clash.yml
60
+ - test/.gitignore
61
+ - test/Gemfile
62
+ - test/_config.yml
63
+ - test/_expected/boom
64
+ - test/_expected/magic
65
+ - test/_expected/merge_payload.html
66
+ - test/_expected/post_render_page.html
67
+ - test/_expected/post_write_page.html
68
+ - test/_expected/pre_render_page.html
69
+ - test/_plugins/test.rb
70
+ - test/merge_payload.md
71
+ - test/post_render_page.md
72
+ - test/post_write_page.md
73
+ - test/pre_render_page.md
74
+ homepage: http://github.com/octopress/hooks
75
+ licenses:
76
+ - MIT
77
+ metadata: {}
78
+ post_install_message:
79
+ rdoc_options: []
80
+ require_paths:
81
+ - lib
82
+ required_ruby_version: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ required_rubygems_version: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ requirements: []
93
+ rubyforge_project:
94
+ rubygems_version: 2.2.2
95
+ signing_key:
96
+ specification_version: 4
97
+ summary: Allows access to Jekyll's site, posts and pages at different points in the
98
+ life cycle of a build. Formerly known as 'jekyll-page-hooks'.
99
+ test_files: []