Skip to content
This repository was archived by the owner on Jan 12, 2021. It is now read-only.

Commit 396e7cf

Browse files
author
James Ramsay
committed
Merge pull request #1 from jamesramsay/prototype
Initial release
2 parents 342c8bd + eb9c15d commit 396e7cf

35 files changed

+563
-15
lines changed

Diff for: .gitignore

+2-14
Original file line numberDiff line numberDiff line change
@@ -5,32 +5,20 @@
55
/InstalledFiles
66
/pkg/
77
/spec/reports/
8+
/spec/dest/
89
/spec/examples.txt
910
/test/tmp/
1011
/test/version_tmp/
1112
/tmp/
1213

13-
## Specific to RubyMotion:
14-
.dat*
15-
.repl_history
16-
build/
17-
18-
## Documentation cache and generated files:
19-
/.yardoc/
20-
/_yardoc/
21-
/doc/
22-
/rdoc/
23-
2414
## Environment normalization:
2515
/.bundle/
2616
/vendor/bundle
2717
/lib/bundler/man/
2818

2919
# for a library or gem, you might want to ignore these files since the code is
3020
# intended to run in multiple environments; otherwise, check them in:
31-
# Gemfile.lock
32-
# .ruby-version
33-
# .ruby-gemset
21+
Gemfile.lock
3422

3523
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
3624
.rvmrc

Diff for: .travis.yml

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
language: ruby
2+
rvm:
3+
- 2.2.3
4+
script:
5+
- rake

Diff for: Gemfile

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
source "https://rubygems.org"
2+
gemspec
3+
4+
if ENV["JEKYLL_VERSION"]
5+
gem "jekyll", "~> #{ENV["JEKYLL_VERSION"]}"
6+
end

Diff for: History.markdown

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
## 0.1.0 / 2016-01-01
2+
3+
* Birthday!
4+
5+
## 0.0.0 / 2016-02-24
6+
7+
* Alpha

Diff for: README.md

+34-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,34 @@
1-
# jekyll-app-engine
1+
# jekyll-app-engine: deploy your site to Google App Engine
2+
3+
[![Build Status](https://img.shields.io/travis/jamesramsay/jekyll-app-engine/master.svg)](https://travis-ci.org/jamesramsay/jekyll-app-engine)
4+
[![Version](https://img.shields.io/gem/v/jekyll-app-engine.svg)](https://rubygems.org/gems/jekyll-app-engine)
5+
6+
`jekyll-app-engine` makes it easy to deploy your jekyll site to Google App Engine by generating handlers for your `app.yaml`.
7+
8+
Using Google App Engine to host your Jekyll site has the following benefits:
9+
10+
- HTTPS
11+
- HTTP cache control for pages and assets
12+
- HTTP/2 support including PUSH
13+
- Use custom jekyll plugins not supported by Github Pages
14+
- Google CDN
15+
16+
Limitations:
17+
18+
- 404 handling not customisable
19+
20+
## Usage
21+
22+
Add `gem jekyll-app-engine` to your Gemfile:
23+
24+
```
25+
source 'https://rubygems.org'
26+
gem 'github-pages'
27+
gem 'jekyll-app-engine'
28+
```
29+
30+
Add configs...
31+
32+
## Documentation
33+
34+
todo

Diff for: Rakefile

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
require "bundler/gem_tasks"
2+
require 'rspec/core/rake_task'
3+
4+
RSpec::Core::RakeTask.new(:spec)
5+
6+
task :default => :spec

Diff for: jekyll-app-engine.gemspec

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
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.0.1"
7+
spec.authors = ["James Ramsay"]
8+
spec.email = "[email protected] "
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+
end

Diff for: lib/app.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{{ content }}

Diff for: lib/jekyll-app-engine.rb

+163
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
require 'fileutils'
2+
3+
module Jekyll
4+
5+
class GoogleYAMLTree < Psych::Visitors::YAMLTree
6+
def accept target
7+
if target.respond_to?(:to_yaml)
8+
begin
9+
loc = target.method(:to_yaml).source_location.first
10+
if loc !~ /(syck\/rubytypes.rb|psych\/core_ext.rb)/
11+
unless target.respond_to?(:encode_with)
12+
if $VERBOSE
13+
warn "implementing to_yaml is deprecated, please implement \"encode_with\""
14+
end
15+
16+
target.to_yaml(:nodump => true)
17+
end
18+
end
19+
rescue
20+
# public_method or source_location might be overridden,
21+
# and it's OK to skip it since it's only to emit a warning
22+
end
23+
end
24+
25+
if target.respond_to?(:encode_with)
26+
dump_coder target
27+
else
28+
send(@dispatch_cache[target.class], target)
29+
end
30+
end
31+
end
32+
33+
class PageWithoutAFile < Page
34+
def read_yaml(*)
35+
@data ||= {}
36+
end
37+
end
38+
39+
class JekyllAppEngine < Jekyll::Generator
40+
safe true
41+
priority :lowest
42+
43+
# Main plugin action, called by Jekyll-core
44+
def generate(site)
45+
@site = site
46+
@app_engine = site.config["app_engine"]
47+
48+
unless app_yaml_exists?
49+
unless @app_engine["base"] or source_partial_exists?
50+
raise "App engine base configration not found"
51+
end
52+
53+
write
54+
@site.keep_files ||= []
55+
@site.keep_files << "app.yaml"
56+
end
57+
end
58+
59+
# Checks if a optional _app.yaml partial already exists
60+
def source_partial_exists?
61+
if @site.respond_to?(:in_source_dir)
62+
File.exists? @site.in_source_dir("_app.yaml")
63+
else
64+
File.exists? Jekyll.sanitized_path(@site.source, "_app.yaml")
65+
end
66+
end
67+
68+
# Path to optional _app.yaml partial
69+
def source_path
70+
if @site.respond_to?(:in_source_dir)
71+
@site.in_source_dir("_app.yaml")
72+
else
73+
Jekyll.sanitized_path(@site.source, "_app.yaml")
74+
end
75+
end
76+
77+
# Destination for app.yaml file within the site source directory
78+
def destination_path
79+
if @site.respond_to?(:in_dest_dir)
80+
@site.in_dest_dir("app.yaml")
81+
else
82+
Jekyll.sanitized_path(@site.dest, "app.yaml")
83+
end
84+
end
85+
86+
def write
87+
FileUtils.mkdir_p File.dirname(destination_path)
88+
File.open(destination_path, 'w') { |f| f.write(app_yaml_content) }
89+
end
90+
91+
def app_yaml_content
92+
builder = GoogleYAMLTree.create
93+
builder << generate_app_engine_yaml
94+
95+
app_yaml = PageWithoutAFile.new(@site, File.dirname(__FILE__), "", "app.yaml")
96+
app_yaml.content = builder.tree.yaml
97+
app_yaml.data["layout"] = nil
98+
app_yaml.render({}, @site.site_payload)
99+
return app_yaml.output
100+
end
101+
102+
def generate_app_engine_yaml
103+
if source_partial_exists?
104+
app_yaml = YAML.load_file(source_path)
105+
else
106+
app_yaml = @app_engine["base"].dup
107+
end
108+
109+
app_yaml["handlers"] ||= []
110+
111+
generate_handlers("posts", @site.posts.docs).each { |handler| app_yaml["handlers"] << handler }
112+
generate_handlers("pages", @site.pages).each { |handler| app_yaml["handlers"] << handler }
113+
114+
@site.collections.each_pair do |label, collection|
115+
unless label == "posts"
116+
generate_handlers("collections", collection.docs).each { |handler| app_yaml["handlers"] << handler }
117+
end
118+
end
119+
120+
generate_handlers("static", @site.static_files).each { |handler| app_yaml["handlers"] << handler }
121+
122+
return app_yaml
123+
end
124+
125+
def generate_handlers(content_type, collection)
126+
handlers = []
127+
128+
handler_template = @app_engine["handlers"][content_type] || {}
129+
if handler_template.kind_of?(Array) or handler_template.has_key?("url")
130+
handlers << handler_template
131+
else
132+
collection.each do |doc|
133+
handler = {
134+
"url" => doc.url,
135+
"static_files" => doc.destination("").sub("#{Dir.pwd}/", ""),
136+
"upload" => doc.destination("").sub("#{Dir.pwd}/", "")
137+
}
138+
handlers << handler.merge!(handler_template.dup).merge!(document_overrides(doc))
139+
end
140+
end
141+
142+
return handlers
143+
end
144+
145+
# Document specific app.yaml configuration provided in yaml frontmatter
146+
def document_overrides(document)
147+
if document.respond_to?(:data) and document.data.has_key?("app_engine")
148+
document.data.fetch("app_engine")
149+
else
150+
{}
151+
end
152+
end
153+
154+
# Checks if a app.yaml already exists in the site source
155+
def app_yaml_exists?
156+
if @site.respond_to?(:in_source_dir)
157+
File.exists? @site.in_source_dir("app.yaml")
158+
else
159+
File.exists? Jekyll.sanitized_path(@site.source, "app.yaml")
160+
end
161+
end
162+
end
163+
end

Diff for: script/bootstrap

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/bin/sh
2+
3+
bundle install

Diff for: script/cibuild

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#!/bin/sh
2+
set -e
3+
4+
bundle exec rspec

Diff for: script/console

+34
Original file line numberDiff line numberDiff line change
@@ -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

Diff for: script/release

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#!/bin/sh
2+
# Tag and push a release.
3+
4+
set -e
5+
6+
script/cibuild
7+
bundle exec rake release

Diff for: spec/fixtures/_config.yml

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
timezone: UTC
2+
3+
defaults:
4+
-
5+
scope:
6+
path: ""
7+
type: page
8+
values:
9+
layout: some_default
10+
11+
app_engine:
12+
base:
13+
runtime: go
14+
api_version: go1
15+
default_expiration: 300s
16+
handlers:
17+
posts:
18+
http_headers:
19+
Link: "</static/css/style.css>; rel=preload; as=style"
20+
statics:
21+
- url: /images/
22+
static_dir: _site/images
23+
expiration: 4m
24+
- url: /styles/
25+
static_dir: _site/styles
26+
expiration: 8m

Diff for: spec/fixtures/_layouts/some_default.html

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
---
3+
THIS IS MY LAYOUT
4+
{{ content }}

Diff for: spec/fixtures/_my_collection/custom_permalink.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
permalink: /permalink/
3+
---
4+
5+
# Custom permalink

Diff for: spec/fixtures/_my_collection/custom_permalink_2.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
permalink: /permalink/unique_name.html
3+
---
4+
5+
# Unique html name

Diff for: spec/fixtures/_my_collection/test.html

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
---
3+
4+
This is just a test.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
permalink: this url has an ümlaut
3+
---
4+
5+
# URL contains characters that need to be URI encoded

Diff for: spec/fixtures/_other_things/test2.html

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
---
3+
4+
This file shouldn't show up in the app.yaml.

0 commit comments

Comments
 (0)