jekyll-app-engine 0.1.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.
- checksums.yaml +15 -0
- data/.gitignore +24 -0
- data/.simplecov +3 -0
- data/.travis.yml +12 -0
- data/Gemfile +6 -0
- data/History.markdown +7 -0
- data/LICENSE +21 -0
- data/README.md +97 -0
- data/Rakefile +6 -0
- data/jekyll-app-engine.gemspec +22 -0
- data/lib/app.yaml +1 -0
- data/lib/google-yaml.rb +42 -0
- data/lib/jekyll-app-engine.rb +171 -0
- data/script/bootstrap +3 -0
- data/script/cibuild +4 -0
- data/script/console +34 -0
- data/script/release +7 -0
- data/spec/fixtures/_app.yaml +11 -0
- data/spec/fixtures/_config.yml +9 -0
- data/spec/fixtures/_layouts/some_default.html +4 -0
- data/spec/fixtures/_my_collection/custom_permalink.md +5 -0
- data/spec/fixtures/_my_collection/custom_permalink_2.md +5 -0
- data/spec/fixtures/_my_collection/test.html +4 -0
- data/spec/fixtures/_my_collection/this-has-non-standard-chars.md +5 -0
- data/spec/fixtures/_other_things/test2.html +4 -0
- data/spec/fixtures/_posts/2013-12-12-dec-the-second.md +4 -0
- data/spec/fixtures/_posts/2014-03-02-march-the-second.md +4 -0
- data/spec/fixtures/_posts/2014-03-04-march-the-fourth.md +4 -0
- data/spec/fixtures/_posts/2015-01-18-jekyll-last-modified-at.md +4 -0
- data/spec/fixtures/feeds/atom.xml +6 -0
- data/spec/fixtures/images/hubot.png +0 -0
- data/spec/fixtures/index.html +7 -0
- data/spec/fixtures/jekyll-last-modified-at/page.html +4 -0
- data/spec/fixtures/some-subfolder/htm.htm +1 -0
- data/spec/fixtures/some-subfolder/test_index.html +4 -0
- data/spec/fixtures/some-subfolder/this-is-a-subfile.html +0 -0
- data/spec/fixtures/some-subfolder/this-is-a-subpage.html +4 -0
- data/spec/fixtures/some-subfolder/xhtml.xhtml +1 -0
- data/spec/jekyll-app-engine_spec.rb +131 -0
- data/spec/spec_helper.rb +28 -0
- metadata +175 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
!binary "U0hBMQ==":
|
|
3
|
+
metadata.gz: !binary |-
|
|
4
|
+
MTA0NWU4YTkxMDBlODhlOGE1YzRlMzNmZTg4MjE3MTM3ZTJlMDcyZA==
|
|
5
|
+
data.tar.gz: !binary |-
|
|
6
|
+
YTRlNjQwYzAxNzRmYTNjN2RmNWIzN2M0MTNjMzExZWMyM2RlOTlkMg==
|
|
7
|
+
SHA512:
|
|
8
|
+
metadata.gz: !binary |-
|
|
9
|
+
ZDQ5N2M2OTZkMzVhMDcxMzk0MDhiOWZiMjE0NWM3NmVkNTUwOTliNDZhM2Ji
|
|
10
|
+
ZTFiOWI4ZmU5ZTBlNmM1MDcyNGFhM2JkN2U0ZTZjYjBiZDdlOTBiMDNkYTM2
|
|
11
|
+
ZDNkNTE4Y2ZlZTA5OWVlNjc3OWYwZTQxOTRmZWI1OWRkMTNlZGM=
|
|
12
|
+
data.tar.gz: !binary |-
|
|
13
|
+
ZjU5OThlMTU2MjU2NDQzNjdmMDhlYzU2MTI3MTM4NDlmZDM1Yzg3MjhjM2Yw
|
|
14
|
+
Y2JmMDQyNGZlNzI0ZjM2MTAzOGJiOTJhYjBjNDU0NmJhZjRhM2Q1N2M4YWQ4
|
|
15
|
+
MDg1ODdhZGUwMzJhZGY5ZmZjMWUwNjU5MGMzNzA2YzMzM2I3YTI=
|
data/.gitignore
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
*.gem
|
|
2
|
+
*.rbc
|
|
3
|
+
/.config
|
|
4
|
+
/coverage/
|
|
5
|
+
/InstalledFiles
|
|
6
|
+
/pkg/
|
|
7
|
+
/spec/reports/
|
|
8
|
+
/spec/dest/
|
|
9
|
+
/spec/examples.txt
|
|
10
|
+
/test/tmp/
|
|
11
|
+
/test/version_tmp/
|
|
12
|
+
/tmp/
|
|
13
|
+
|
|
14
|
+
## Environment normalization:
|
|
15
|
+
/.bundle/
|
|
16
|
+
/vendor/bundle
|
|
17
|
+
/lib/bundler/man/
|
|
18
|
+
|
|
19
|
+
# for a library or gem, you might want to ignore these files since the code is
|
|
20
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
21
|
+
Gemfile.lock
|
|
22
|
+
|
|
23
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
|
24
|
+
.rvmrc
|
data/.simplecov
ADDED
data/.travis.yml
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
language: ruby
|
|
2
|
+
rvm:
|
|
3
|
+
- 2.2.3
|
|
4
|
+
script:
|
|
5
|
+
- rake
|
|
6
|
+
deploy:
|
|
7
|
+
provider: rubygems
|
|
8
|
+
gemspec: jekyll-app-engine.gemspec
|
|
9
|
+
api_key:
|
|
10
|
+
secure: gEbhxtKjKEz7JIez+hljl1IJMq8fyUOGKIXJWTWJnF4U3NZPHTq+Wv1AQKsgI80NpqTpCDTOfbiCPJ0Iti8XObkNjtfa7k9CNs/2MvQYcIWaDWP6ibgHTKZptiLh3IP+lkK3z2ZRvl4vaP/v2qKC16oaazqoli7Um0gj9dbX2A2PjxN9BZGMfgV1C3U1Igri7OWu37vVapuPvQ8NgeXOO8wWjP5tlJ2oOl0yHVXOVkw5Dwv8jpiFF0srz+lH+2FRG7yAZ95850okpNsyka+AOA1dJzBGZpyAwN3WCPQU0bsirijjDBdWpI0sxtSQFPA7z4up0PUv4/x34k9EtYjs31Xm4rtpItUiE7bgC8MVc4Li0gxhKuSQmAXozJHErM5GQZzeUUaaZffVbtKZsZUS2BX0zuRUO+22Jjfeh/nUkNiDPKVIIp5n7e2UPuGSruBy9t6GlR17KmLJ1uFV+a6WxTPlAUwS82WIuVdTzn2XrWc0WNLAHHfO3wJqFhwtGlowgmS7c7RTvc7MNkNk25e6P/p8TrEhameOxEjl6x7+lHXNZY6ssPwazGPagy2T39kSS/alCNYLuAIEkcFArM/c7tXPoajbYxpDdRJzmQm0ipKZ/xUp/Ij2GG3hF+Oq/9vBBF6/7oCLrC6Gynq7rXUlTaZURTkY3AzZQXlvmmYK4Ww=
|
|
11
|
+
on:
|
|
12
|
+
tags: true
|
data/Gemfile
ADDED
data/History.markdown
ADDED
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2016 James Ramsay
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# Jekyll App Engine: easy deployments to Google App Engine
|
|
2
|
+
|
|
3
|
+
[](https://travis-ci.org/jamesramsay/jekyll-app-engine)
|
|
4
|
+
[](https://rubygems.org/gems/jekyll-app-engine)
|
|
5
|
+
[](https://codecov.io/github/jamesramsay/jekyll-app-engine)
|
|
6
|
+
|
|
7
|
+
Jekyll App Engine (`jekyll-app-engine`) makes it easy to deploy your [Jekyll](http://jekyll.com) static site to [Google App Engine](https://appengine.google.com) by generating your `app.yaml` handlers.
|
|
8
|
+
|
|
9
|
+
Hosting your static site on Google App Engine gives you greater flexibility than using Github Pages and may potentially be cheaper and more configurable than Amazon AWS.
|
|
10
|
+
Using Google App Engine allows:
|
|
11
|
+
|
|
12
|
+
- fine grained HTTP cache control for pages and assets,
|
|
13
|
+
- HTTP/2 support including server push `Link: "</assets/style.css>; rel=preload; as=style,"`, and
|
|
14
|
+
- custom jekyll plugins not permitted by Github Pages, such as [`jekyll-assets`](http://github.com/jekyll/jekyll-assets)
|
|
15
|
+
|
|
16
|
+
Using Google App Engine has some challenges:
|
|
17
|
+
|
|
18
|
+
- Customising handling of 404 errors can only be done by running an application instance, which may be costly.
|
|
19
|
+
|
|
20
|
+
## Get Started
|
|
21
|
+
|
|
22
|
+
These instructions assume you already have a [Google App Engine account](https://console.cloud.google.com/).
|
|
23
|
+
|
|
24
|
+
### 1. Install jekyll-app-engine
|
|
25
|
+
|
|
26
|
+
Add `gem jekyll-app-engine` to your `Gemfile`.
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
source 'https://rubygems.org'
|
|
30
|
+
gem 'github-pages'
|
|
31
|
+
gem 'jekyll-app-engine'
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Add to your `config.yml`.
|
|
35
|
+
|
|
36
|
+
```yaml
|
|
37
|
+
gems:
|
|
38
|
+
- jekyll-app-engine
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### 2. Basic configuration
|
|
42
|
+
|
|
43
|
+
Specify a basic configuration in the file `_app.yaml` or using the `app_engine` option configurations to your Jekyll `_config.yml`.
|
|
44
|
+
|
|
45
|
+
```yaml
|
|
46
|
+
app_engine:
|
|
47
|
+
# Insert your configuration here or within _app.yaml
|
|
48
|
+
# You need to specify a runtime for App Engine
|
|
49
|
+
runtime: go
|
|
50
|
+
api_version: go1
|
|
51
|
+
default_expiration: 300s
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### 3. Create an empty 'app'
|
|
55
|
+
|
|
56
|
+
App Engine expects all apps to have some sort of application.
|
|
57
|
+
Create a file called `init.go`.
|
|
58
|
+
|
|
59
|
+
```go
|
|
60
|
+
// Included to enable deployment to Google App Engine
|
|
61
|
+
package hello
|
|
62
|
+
|
|
63
|
+
import (
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
func init() {
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
You can put this anywhere, for example in a folder `_app/init.go` to keep your root tidy.
|
|
71
|
+
|
|
72
|
+
### 4. Test and Deploy
|
|
73
|
+
|
|
74
|
+
Build your jekyll site, and you should notice the file `app.yaml` in the output directory.
|
|
75
|
+
Before deploying you will need to move this file to the projects root directory, where your `config.yml` file is located.
|
|
76
|
+
|
|
77
|
+
Automatic deployment using Travis: https://docs.travis-ci.com/user/deployment/google-app-engine
|
|
78
|
+
|
|
79
|
+
Manual deployment using the Google App Engine tools: todo
|
|
80
|
+
|
|
81
|
+
## Documentation
|
|
82
|
+
|
|
83
|
+
### Basic Configuration
|
|
84
|
+
|
|
85
|
+
jekyll-app-engine can be configured by creating a file `_app.yaml` in the source directory or by providing the configuration in the Jekyll config `_config.yml`.
|
|
86
|
+
The `handlers` option allows you to specify custom http headers and other feature supported by Google App Engine by Jekyll content type. The supported content types are:
|
|
87
|
+
|
|
88
|
+
- `posts`
|
|
89
|
+
- `pages`
|
|
90
|
+
- `collections`
|
|
91
|
+
- `static`
|
|
92
|
+
|
|
93
|
+
If you provide an Array or a `url` option, the configuration for the content type will be inserted directly as a handler, instead of generating a handler per item within the content type.
|
|
94
|
+
|
|
95
|
+
### Document Specific Overrides
|
|
96
|
+
|
|
97
|
+
Each document can specify overrides within the document's YAML frontmatter.
|
data/Rakefile
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
|
|
3
|
+
Gem::Specification.new do |spec|
|
|
4
|
+
spec.name = "jekyll-app-engine"
|
|
5
|
+
spec.summary = "Generator for Google App Engine Handlers."
|
|
6
|
+
spec.version = "0.1.0"
|
|
7
|
+
spec.authors = ["James Ramsay"]
|
|
8
|
+
spec.email = "git@jwr.vc"
|
|
9
|
+
spec.homepage = "http://github.com/jamesramsay/jekyll-app-engine"
|
|
10
|
+
spec.licenses = ["MIT"]
|
|
11
|
+
|
|
12
|
+
spec.files = `git ls-files -z`.split("\x0")
|
|
13
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
|
14
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
|
15
|
+
spec.require_paths = ["lib"]
|
|
16
|
+
|
|
17
|
+
spec.add_development_dependency "jekyll", ">= 2.0"
|
|
18
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
|
19
|
+
spec.add_development_dependency "rake"
|
|
20
|
+
spec.add_development_dependency "bundler", "~> 1.6"
|
|
21
|
+
spec.add_development_dependency "codecov"
|
|
22
|
+
end
|
data/lib/app.yaml
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{{ content }}
|
data/lib/google-yaml.rb
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Google App Engine doesn't support achors and alias feature of YAML
|
|
2
|
+
# Psych doesn't provide an option to disable achors/alias YAML features
|
|
3
|
+
#
|
|
4
|
+
# HACK: subclass the native YAMLTree, and bypass logic which checks for aliases
|
|
5
|
+
# ../psych/vistors/yaml_tree.rb
|
|
6
|
+
class GoogleYAMLTree < Psych::Visitors::YAMLTree
|
|
7
|
+
def accept target
|
|
8
|
+
# HACK: disabled alias lookup
|
|
9
|
+
# return any aliases we find
|
|
10
|
+
# if @st.key? target
|
|
11
|
+
# oid = @st.id_for target
|
|
12
|
+
# node = @st.node_for target
|
|
13
|
+
# anchor = oid.to_s
|
|
14
|
+
# node.anchor = anchor
|
|
15
|
+
# return @emitter.alias anchor
|
|
16
|
+
# end
|
|
17
|
+
|
|
18
|
+
if target.respond_to?(:to_yaml)
|
|
19
|
+
begin
|
|
20
|
+
loc = target.method(:to_yaml).source_location.first
|
|
21
|
+
if loc !~ /(syck\/rubytypes.rb|psych\/core_ext.rb)/
|
|
22
|
+
unless target.respond_to?(:encode_with)
|
|
23
|
+
if $VERBOSE
|
|
24
|
+
warn "implementing to_yaml is deprecated, please implement \"encode_with\""
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
target.to_yaml(:nodump => true)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
rescue
|
|
31
|
+
# public_method or source_location might be overridden,
|
|
32
|
+
# and it's OK to skip it since it's only to emit a warning
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
if target.respond_to?(:encode_with)
|
|
37
|
+
dump_coder target
|
|
38
|
+
else
|
|
39
|
+
send(@dispatch_cache[target.class], target)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
require 'fileutils'
|
|
2
|
+
require 'google-yaml'
|
|
3
|
+
|
|
4
|
+
module Jekyll
|
|
5
|
+
|
|
6
|
+
class PageWithoutAFile < Page
|
|
7
|
+
def read_yaml(*)
|
|
8
|
+
@data ||= {}
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
class JekyllAppEngine < Jekyll::Generator
|
|
13
|
+
safe true
|
|
14
|
+
priority :lowest
|
|
15
|
+
|
|
16
|
+
# Main plugin action, called by Jekyll-core
|
|
17
|
+
def generate(site)
|
|
18
|
+
@site = site
|
|
19
|
+
@app_engine = source_config
|
|
20
|
+
|
|
21
|
+
unless app_yaml_exists?
|
|
22
|
+
unless @app_engine
|
|
23
|
+
raise "App engine base configration not found"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
@app_engine["handlers"] ||= {}
|
|
27
|
+
|
|
28
|
+
write
|
|
29
|
+
@site.keep_files ||= []
|
|
30
|
+
@site.keep_files << "app.yaml"
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def source_config
|
|
35
|
+
if @site.config.has_key?("app_engine")
|
|
36
|
+
@site.config["app_engine"]
|
|
37
|
+
elsif source_partial_exists?
|
|
38
|
+
YAML.load_file(source_path)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Checks if a optional _app.yaml partial already exists
|
|
43
|
+
def source_partial_exists?
|
|
44
|
+
if @site.respond_to?(:in_source_dir)
|
|
45
|
+
File.exists? @site.in_source_dir("_app.yaml")
|
|
46
|
+
else
|
|
47
|
+
File.exists? Jekyll.sanitized_path(@site.source, "_app.yaml")
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Path to optional _app.yaml partial
|
|
52
|
+
def source_path
|
|
53
|
+
if @site.respond_to?(:in_source_dir)
|
|
54
|
+
@site.in_source_dir("_app.yaml")
|
|
55
|
+
else
|
|
56
|
+
Jekyll.sanitized_path(@site.source, "_app.yaml")
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Destination for app.yaml file within the site source directory
|
|
61
|
+
def destination_path
|
|
62
|
+
if @site.respond_to?(:in_dest_dir)
|
|
63
|
+
@site.in_dest_dir("app.yaml")
|
|
64
|
+
else
|
|
65
|
+
Jekyll.sanitized_path(@site.dest, "app.yaml")
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def write
|
|
70
|
+
FileUtils.mkdir_p File.dirname(destination_path)
|
|
71
|
+
File.open(destination_path, 'w') { |f| f.write(app_yaml_content) }
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def app_yaml_content
|
|
75
|
+
# HACK: use sub-classed YAML implementation which disables anchors and aliases
|
|
76
|
+
builder = GoogleYAMLTree.create
|
|
77
|
+
builder << generate_app_engine_yaml
|
|
78
|
+
|
|
79
|
+
app_yaml = PageWithoutAFile.new(@site, File.dirname(__FILE__), "", "app.yaml")
|
|
80
|
+
app_yaml.content = builder.tree.yaml
|
|
81
|
+
app_yaml.data["layout"] = nil
|
|
82
|
+
app_yaml.render({}, @site.site_payload)
|
|
83
|
+
return app_yaml.output
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def output_collection?(label)
|
|
87
|
+
@site.config["collections"]["#{label}"]["output"]
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def page_types
|
|
91
|
+
page_types_array = [
|
|
92
|
+
{
|
|
93
|
+
"content_type" => "posts",
|
|
94
|
+
"content_collection" => @site.posts.docs
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
"content_type" => "pages",
|
|
98
|
+
"content_collection" => @site.pages
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
"content_type" => "static",
|
|
102
|
+
"content_collection" => @site.static_files
|
|
103
|
+
},
|
|
104
|
+
]
|
|
105
|
+
|
|
106
|
+
@site.collections.each_pair do |label, collection|
|
|
107
|
+
if label != "posts" and output_collection?(label)
|
|
108
|
+
page_types_array << {
|
|
109
|
+
"content_type" => "collections",
|
|
110
|
+
"content_collection" => collection.docs
|
|
111
|
+
}
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
return page_types_array
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def generate_app_engine_yaml
|
|
119
|
+
app_yaml = @app_engine.dup
|
|
120
|
+
generated_handlers = []
|
|
121
|
+
|
|
122
|
+
page_types.each do |content|
|
|
123
|
+
generate_handlers(content).each { |handler| generated_handlers << handler }
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
app_yaml["handlers"] = generated_handlers
|
|
127
|
+
|
|
128
|
+
return app_yaml
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def generate_handlers(content)
|
|
132
|
+
content_type = content["content_type"]
|
|
133
|
+
content_collection = content["content_collection"]
|
|
134
|
+
handlers = []
|
|
135
|
+
|
|
136
|
+
handler_template = @app_engine["handlers"][content_type] || {}
|
|
137
|
+
if handler_template.kind_of?(Array) or handler_template.has_key?("url")
|
|
138
|
+
handlers << handler_template
|
|
139
|
+
else
|
|
140
|
+
content_collection.each do |doc|
|
|
141
|
+
handler = {
|
|
142
|
+
"url" => doc.url,
|
|
143
|
+
"static_files" => doc.destination("").sub("#{Dir.pwd}/", ""),
|
|
144
|
+
"upload" => doc.destination("").sub("#{Dir.pwd}/", "")
|
|
145
|
+
}
|
|
146
|
+
handlers << handler.merge!(handler_template.dup).merge!(document_overrides(doc))
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
return handlers
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
# Document specific app.yaml configuration provided in yaml frontmatter
|
|
154
|
+
def document_overrides(document)
|
|
155
|
+
if document.respond_to?(:data) and document.data.has_key?("app_engine")
|
|
156
|
+
document.data.fetch("app_engine")
|
|
157
|
+
else
|
|
158
|
+
{}
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# Checks if a app.yaml already exists in the site source
|
|
163
|
+
def app_yaml_exists?
|
|
164
|
+
if @site.respond_to?(:in_source_dir)
|
|
165
|
+
File.exists? @site.in_source_dir("app.yaml")
|
|
166
|
+
else
|
|
167
|
+
File.exists? Jekyll.sanitized_path(@site.source, "app.yaml")
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
end
|
data/script/bootstrap
ADDED
data/script/cibuild
ADDED
data/script/console
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#! /usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
def relative_to_root(path)
|
|
4
|
+
File.expand_path(path, File.dirname(File.dirname(__FILE__)))
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
require 'jekyll'
|
|
8
|
+
require relative_to_root('lib/jekyll-app-engine.rb')
|
|
9
|
+
require 'pry-debugger'
|
|
10
|
+
|
|
11
|
+
SOURCE_DIR = relative_to_root('spec/fixtures')
|
|
12
|
+
DEST_DIR = relative_to_root('spec/dest')
|
|
13
|
+
|
|
14
|
+
def source_dir(*files)
|
|
15
|
+
File.join(SOURCE_DIR, *files)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def dest_dir(*files)
|
|
19
|
+
File.join(DEST_DIR, *files)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def config(overrides = {})
|
|
23
|
+
Jekyll.configuration({
|
|
24
|
+
"source" => source_dir,
|
|
25
|
+
"destination" => dest_dir,
|
|
26
|
+
"url" => "http://example.org"
|
|
27
|
+
}).merge(overrides)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def site(configuration = config)
|
|
31
|
+
Jekyll::Site.new(configuration)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
binding.pry
|
data/script/release
ADDED
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
This file has an .htm extension, and should be included in the app.yaml
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
This file has an .xhtml extension, and should be included in the app.yaml
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
describe(Jekyll::JekyllAppEngine) do
|
|
6
|
+
let(:overrides) do
|
|
7
|
+
{
|
|
8
|
+
"source" => source_dir,
|
|
9
|
+
"destination" => dest_dir,
|
|
10
|
+
"url" => "http://example.org",
|
|
11
|
+
"collections" => {
|
|
12
|
+
"my_collection" => { "output" => true },
|
|
13
|
+
"other_things" => { "output" => false }
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
end
|
|
17
|
+
let(:config) do
|
|
18
|
+
Jekyll.configuration(overrides)
|
|
19
|
+
end
|
|
20
|
+
let(:site) { Jekyll::Site.new(config) }
|
|
21
|
+
let(:contents) { File.read(dest_dir("app.yaml")) }
|
|
22
|
+
let(:app_yaml) { YAML.load_file(dest_dir("app.yaml")) }
|
|
23
|
+
let(:handlers) { app_yaml["handlers"] }
|
|
24
|
+
before(:each) do
|
|
25
|
+
site.process
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it "has no layout" do
|
|
29
|
+
expect(contents).not_to match(/\ATHIS IS MY LAYOUT/)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it "creates an app.yaml file" do
|
|
33
|
+
expect(File.exist?(dest_dir("app.yaml"))).to be_truthy
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it "doesn't have multiple new lines or trailing whitespace" do
|
|
37
|
+
expect(contents).to_not match /\s+\n/
|
|
38
|
+
expect(contents).to_not match /\n{2,}/
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it "puts all the pages in the app.yaml file" do
|
|
42
|
+
expect(handlers).to include({
|
|
43
|
+
"url" => "/",
|
|
44
|
+
"static_files" => "spec/dest/index.html",
|
|
45
|
+
"upload" => "spec/dest/index.html",
|
|
46
|
+
"http_headers" => {
|
|
47
|
+
"Cache-Control" => "max-age=3600"
|
|
48
|
+
}
|
|
49
|
+
})
|
|
50
|
+
expect(handlers).to include({
|
|
51
|
+
"url" => "/some-subfolder/this-is-a-subpage.html",
|
|
52
|
+
"static_files" => "spec/dest/some-subfolder/this-is-a-subpage.html",
|
|
53
|
+
"upload" => "spec/dest/some-subfolder/this-is-a-subpage.html"
|
|
54
|
+
})
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it "only strips 'index.html' from end of permalink" do
|
|
58
|
+
expect(handlers).to include({
|
|
59
|
+
"url" => "/some-subfolder/test_index.html",
|
|
60
|
+
"static_files" => "spec/dest/some-subfolder/test_index.html",
|
|
61
|
+
"upload" => "spec/dest/some-subfolder/test_index.html"
|
|
62
|
+
})
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it "puts all the posts in the app.yaml file" do
|
|
66
|
+
expect(handlers).to include({
|
|
67
|
+
"url" => "/2013/12/12/dec-the-second.html",
|
|
68
|
+
"static_files" => "spec/dest/2013/12/12/dec-the-second.html",
|
|
69
|
+
"upload" => "spec/dest/2013/12/12/dec-the-second.html",
|
|
70
|
+
"http_headers" => {
|
|
71
|
+
"Link" => "</static/css/style.css>; rel=preload; as=style"
|
|
72
|
+
}
|
|
73
|
+
})
|
|
74
|
+
expect(handlers).to include({
|
|
75
|
+
"url" => "/2014/03/02/march-the-second.html",
|
|
76
|
+
"static_files" => "spec/dest/2014/03/02/march-the-second.html",
|
|
77
|
+
"upload" => "spec/dest/2014/03/02/march-the-second.html",
|
|
78
|
+
"http_headers" => {
|
|
79
|
+
"Link" => "</static/css/style.css>; rel=preload; as=style"
|
|
80
|
+
}
|
|
81
|
+
})
|
|
82
|
+
expect(handlers).to include({
|
|
83
|
+
"url" => "/2014/03/04/march-the-fourth.html",
|
|
84
|
+
"static_files" => "spec/dest/2014/03/04/march-the-fourth.html",
|
|
85
|
+
"upload" => "spec/dest/2014/03/04/march-the-fourth.html",
|
|
86
|
+
"http_headers" => {
|
|
87
|
+
"Link" => "</static/css/style.css>; rel=preload; as=style"
|
|
88
|
+
}
|
|
89
|
+
})
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
describe "collections" do
|
|
93
|
+
it "puts all the `output:true` into app.yaml" do
|
|
94
|
+
expect(handlers).to include({
|
|
95
|
+
"url" => "/my_collection/test.html",
|
|
96
|
+
"static_files" => "spec/dest/my_collection/test.html",
|
|
97
|
+
"upload" => "spec/dest/my_collection/test.html"
|
|
98
|
+
})
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
it "doesn't put all the `output:false` into app.yaml" do
|
|
102
|
+
expect(contents).to_not match /\/other_things\/test2\.html/
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
it "puts all the static HTML files in the app.yaml file" do
|
|
107
|
+
expect(handlers).to include({
|
|
108
|
+
"url" => "/some-subfolder/this-is-a-subfile.html",
|
|
109
|
+
"static_files" => "spec/dest/some-subfolder/this-is-a-subfile.html",
|
|
110
|
+
"upload" => "spec/dest/some-subfolder/this-is-a-subfile.html"
|
|
111
|
+
})
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
it "includes the correct number of items" do
|
|
115
|
+
expect(handlers.length).to eql 17
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
context "with a base in _config.yml" do
|
|
119
|
+
let(:config) do
|
|
120
|
+
config_override = { "app_engine" => {
|
|
121
|
+
"runtime" => "python27",
|
|
122
|
+
"api_version" => 1
|
|
123
|
+
} }
|
|
124
|
+
Jekyll.configuration(Jekyll::Utils.deep_merge_hashes(overrides, config_override))
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
it "correctly uses _config.yml runtime" do
|
|
128
|
+
expect(app_yaml["runtime"]).to eql "python27"
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
require 'simplecov'
|
|
2
|
+
|
|
3
|
+
if ENV['CI'] == 'true'
|
|
4
|
+
require 'codecov'
|
|
5
|
+
SimpleCov.formatter = SimpleCov::Formatter::Codecov
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
require 'jekyll'
|
|
9
|
+
require File.expand_path('../lib/jekyll-app-engine', File.dirname(__FILE__))
|
|
10
|
+
|
|
11
|
+
Jekyll.logger.log_level = :error
|
|
12
|
+
|
|
13
|
+
RSpec.configure do |config|
|
|
14
|
+
config.run_all_when_everything_filtered = true
|
|
15
|
+
config.filter_run :focus
|
|
16
|
+
config.order = 'random'
|
|
17
|
+
|
|
18
|
+
SOURCE_DIR = File.expand_path("../fixtures", __FILE__)
|
|
19
|
+
DEST_DIR = File.expand_path("../dest", __FILE__)
|
|
20
|
+
|
|
21
|
+
def source_dir(*files)
|
|
22
|
+
File.join(SOURCE_DIR, *files)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def dest_dir(*files)
|
|
26
|
+
File.join(DEST_DIR, *files)
|
|
27
|
+
end
|
|
28
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: jekyll-app-engine
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- James Ramsay
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2016-03-07 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: :development
|
|
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: rspec
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - ~>
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '3.0'
|
|
34
|
+
type: :development
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - ~>
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '3.0'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: rake
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - ! '>='
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '0'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - ! '>='
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '0'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: bundler
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - ~>
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '1.6'
|
|
62
|
+
type: :development
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - ~>
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '1.6'
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: codecov
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - ! '>='
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: '0'
|
|
76
|
+
type: :development
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - ! '>='
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: '0'
|
|
83
|
+
description:
|
|
84
|
+
email: git@jwr.vc
|
|
85
|
+
executables: []
|
|
86
|
+
extensions: []
|
|
87
|
+
extra_rdoc_files: []
|
|
88
|
+
files:
|
|
89
|
+
- .gitignore
|
|
90
|
+
- .simplecov
|
|
91
|
+
- .travis.yml
|
|
92
|
+
- Gemfile
|
|
93
|
+
- History.markdown
|
|
94
|
+
- LICENSE
|
|
95
|
+
- README.md
|
|
96
|
+
- Rakefile
|
|
97
|
+
- jekyll-app-engine.gemspec
|
|
98
|
+
- lib/app.yaml
|
|
99
|
+
- lib/google-yaml.rb
|
|
100
|
+
- lib/jekyll-app-engine.rb
|
|
101
|
+
- script/bootstrap
|
|
102
|
+
- script/cibuild
|
|
103
|
+
- script/console
|
|
104
|
+
- script/release
|
|
105
|
+
- spec/fixtures/_app.yaml
|
|
106
|
+
- spec/fixtures/_config.yml
|
|
107
|
+
- spec/fixtures/_layouts/some_default.html
|
|
108
|
+
- spec/fixtures/_my_collection/custom_permalink.md
|
|
109
|
+
- spec/fixtures/_my_collection/custom_permalink_2.md
|
|
110
|
+
- spec/fixtures/_my_collection/test.html
|
|
111
|
+
- spec/fixtures/_my_collection/this-has-non-standard-chars.md
|
|
112
|
+
- spec/fixtures/_other_things/test2.html
|
|
113
|
+
- spec/fixtures/_posts/2013-12-12-dec-the-second.md
|
|
114
|
+
- spec/fixtures/_posts/2014-03-02-march-the-second.md
|
|
115
|
+
- spec/fixtures/_posts/2014-03-04-march-the-fourth.md
|
|
116
|
+
- spec/fixtures/_posts/2015-01-18-jekyll-last-modified-at.md
|
|
117
|
+
- spec/fixtures/feeds/atom.xml
|
|
118
|
+
- spec/fixtures/images/hubot.png
|
|
119
|
+
- spec/fixtures/index.html
|
|
120
|
+
- spec/fixtures/jekyll-last-modified-at/page.html
|
|
121
|
+
- spec/fixtures/some-subfolder/htm.htm
|
|
122
|
+
- spec/fixtures/some-subfolder/test_index.html
|
|
123
|
+
- spec/fixtures/some-subfolder/this-is-a-subfile.html
|
|
124
|
+
- spec/fixtures/some-subfolder/this-is-a-subpage.html
|
|
125
|
+
- spec/fixtures/some-subfolder/xhtml.xhtml
|
|
126
|
+
- spec/jekyll-app-engine_spec.rb
|
|
127
|
+
- spec/spec_helper.rb
|
|
128
|
+
homepage: http://github.com/jamesramsay/jekyll-app-engine
|
|
129
|
+
licenses:
|
|
130
|
+
- MIT
|
|
131
|
+
metadata: {}
|
|
132
|
+
post_install_message:
|
|
133
|
+
rdoc_options: []
|
|
134
|
+
require_paths:
|
|
135
|
+
- lib
|
|
136
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
137
|
+
requirements:
|
|
138
|
+
- - ! '>='
|
|
139
|
+
- !ruby/object:Gem::Version
|
|
140
|
+
version: '0'
|
|
141
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
142
|
+
requirements:
|
|
143
|
+
- - ! '>='
|
|
144
|
+
- !ruby/object:Gem::Version
|
|
145
|
+
version: '0'
|
|
146
|
+
requirements: []
|
|
147
|
+
rubyforge_project:
|
|
148
|
+
rubygems_version: 2.4.5
|
|
149
|
+
signing_key:
|
|
150
|
+
specification_version: 4
|
|
151
|
+
summary: Generator for Google App Engine Handlers.
|
|
152
|
+
test_files:
|
|
153
|
+
- spec/fixtures/_app.yaml
|
|
154
|
+
- spec/fixtures/_config.yml
|
|
155
|
+
- spec/fixtures/_layouts/some_default.html
|
|
156
|
+
- spec/fixtures/_my_collection/custom_permalink.md
|
|
157
|
+
- spec/fixtures/_my_collection/custom_permalink_2.md
|
|
158
|
+
- spec/fixtures/_my_collection/test.html
|
|
159
|
+
- spec/fixtures/_my_collection/this-has-non-standard-chars.md
|
|
160
|
+
- spec/fixtures/_other_things/test2.html
|
|
161
|
+
- spec/fixtures/_posts/2013-12-12-dec-the-second.md
|
|
162
|
+
- spec/fixtures/_posts/2014-03-02-march-the-second.md
|
|
163
|
+
- spec/fixtures/_posts/2014-03-04-march-the-fourth.md
|
|
164
|
+
- spec/fixtures/_posts/2015-01-18-jekyll-last-modified-at.md
|
|
165
|
+
- spec/fixtures/feeds/atom.xml
|
|
166
|
+
- spec/fixtures/images/hubot.png
|
|
167
|
+
- spec/fixtures/index.html
|
|
168
|
+
- spec/fixtures/jekyll-last-modified-at/page.html
|
|
169
|
+
- spec/fixtures/some-subfolder/htm.htm
|
|
170
|
+
- spec/fixtures/some-subfolder/test_index.html
|
|
171
|
+
- spec/fixtures/some-subfolder/this-is-a-subfile.html
|
|
172
|
+
- spec/fixtures/some-subfolder/this-is-a-subpage.html
|
|
173
|
+
- spec/fixtures/some-subfolder/xhtml.xhtml
|
|
174
|
+
- spec/jekyll-app-engine_spec.rb
|
|
175
|
+
- spec/spec_helper.rb
|