Merge pull request #764 from mojombo/jekyll-new
`jekyll new`: scaffold site generator
This commit is contained in:
commit
e2d0697f30
|
@ -30,6 +30,15 @@ def normalize_options(options)
|
|||
options
|
||||
end
|
||||
|
||||
command :new do |c|
|
||||
c.syntax = 'jekyll new PATH'
|
||||
c.description = 'Creates a new Jekyll site scaffold in PATH'
|
||||
|
||||
c.action do |args, options|
|
||||
Jekyll::Commands::New.process(args)
|
||||
end
|
||||
end
|
||||
|
||||
command :build do |c|
|
||||
c.syntax = 'jekyll build [options]'
|
||||
c.description = 'Build your site'
|
||||
|
|
|
@ -70,6 +70,8 @@ Gem::Specification.new do |s|
|
|||
lib/jekyll.rb
|
||||
lib/jekyll/command.rb
|
||||
lib/jekyll/commands/build.rb
|
||||
lib/jekyll/commands/migrate.rb
|
||||
lib/jekyll/commands/new.rb
|
||||
lib/jekyll/commands/serve.rb
|
||||
lib/jekyll/converter.rb
|
||||
lib/jekyll/converters/identity.rb
|
||||
|
@ -93,6 +95,15 @@ Gem::Specification.new do |s|
|
|||
lib/jekyll/tags/highlight.rb
|
||||
lib/jekyll/tags/include.rb
|
||||
lib/jekyll/tags/post_url.rb
|
||||
lib/site_template/_config.yml
|
||||
lib/site_template/_layouts/default.html
|
||||
lib/site_template/_layouts/post.html
|
||||
lib/site_template/_posts/0000-00-00-welcome-to-jekyll.markdown.erb
|
||||
lib/site_template/css/screen.css
|
||||
lib/site_template/css/syntax.css
|
||||
lib/site_template/images/.gitkeep
|
||||
lib/site_template/images/rss.png
|
||||
lib/site_template/index.html
|
||||
script/bootstrap
|
||||
site/.gitignore
|
||||
site/CNAME
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
require 'erb'
|
||||
|
||||
module Jekyll
|
||||
module Commands
|
||||
class New < Command
|
||||
def self.process(args)
|
||||
raise ArgumentError.new('You must specify a path.') if args.empty?
|
||||
|
||||
new_blog_path = File.expand_path(args.join(" "), Dir.pwd)
|
||||
FileUtils.mkdir_p new_blog_path
|
||||
|
||||
create_sample_files new_blog_path
|
||||
|
||||
File.open(File.expand_path(self.initialized_post_name, new_blog_path), "w") do |f|
|
||||
f.write(self.scaffold_post_content(site_template))
|
||||
end
|
||||
puts "New jekyll site installed in #{new_blog_path}."
|
||||
end
|
||||
|
||||
def self.scaffold_post_content(template_site)
|
||||
ERB.new(File.read(File.expand_path(scaffold_path, site_template))).result
|
||||
end
|
||||
|
||||
# Internal: Gets the filename of the sample post to be created
|
||||
#
|
||||
# Returns the filename of the sample post, as a String
|
||||
def self.initialized_post_name
|
||||
"_posts/#{Time.now.strftime('%Y-%m-%d')}-welcome-to-jekyll.markdown"
|
||||
end
|
||||
|
||||
private
|
||||
def self.create_sample_files(path)
|
||||
FileUtils.cp_r site_template + '/.', path
|
||||
FileUtils.rm File.expand_path(scaffold_path, path)
|
||||
end
|
||||
|
||||
def self.site_template
|
||||
File.expand_path("../../site_template", File.dirname(__FILE__))
|
||||
end
|
||||
|
||||
def self.scaffold_path
|
||||
"_posts/0000-00-00-welcome-to-jekyll.markdown.erb"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,2 @@
|
|||
markdown: rdiscount
|
||||
pygments: true
|
|
@ -0,0 +1,38 @@
|
|||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en-us">
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<title>{{ page.title }}</title>
|
||||
<!-- syntax highlighting CSS -->
|
||||
<link rel="stylesheet" href="/css/syntax.css" type="text/css" />
|
||||
<!-- Homepage CSS -->
|
||||
<link rel="stylesheet" href="/css/screen.css" type="text/css" media="screen, projection" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="site">
|
||||
<div class="title">
|
||||
<a href="/">Your Name</a>
|
||||
<a class="extra" href="/">home</a>
|
||||
</div>
|
||||
|
||||
{{ content }}
|
||||
|
||||
<div class="footer">
|
||||
<div class="contact">
|
||||
<p>
|
||||
Your Name<br />
|
||||
What You Are<br />
|
||||
your@email.com
|
||||
</p>
|
||||
</div>
|
||||
<div class="contact">
|
||||
<p>
|
||||
<a href="http://github.com/yourusername/">github.com/yourusername</a><br />
|
||||
<a href="http://twitter.com/yourusername/">twitter.com/yourusername</a><br />
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<a href="http://github.com/yourusername"><img style="position: absolute; top: 0; right: 0; border: 0;" src="http://s3.amazonaws.com/github/ribbons/forkme_right_red_aa0000.png" alt="Fork me on GitHub" /></a>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
layout: default
|
||||
---
|
||||
<div id="post">
|
||||
{{ content }}
|
||||
</div>
|
|
@ -0,0 +1,24 @@
|
|||
---
|
||||
layout: post
|
||||
title: "Welcome to Jekyll!"
|
||||
date: <%= Time.now.strftime('%Y-%m-%d %H:%M:%S') %>
|
||||
categories: jekyll update
|
||||
---
|
||||
|
||||
You'll find this post in your `_posts` directory - edit this post and re-build (or run with the `-w` switch) to see your changes!
|
||||
To add new posts, simply add a file in the `_posts` directory that follows the convention: YYYY-MM-DD-name-of-post.ext.
|
||||
|
||||
Jekyll also offers powerful support for code snippets:
|
||||
|
||||
{% highlight ruby %}
|
||||
def print_hi(name)
|
||||
puts "Hi, #{name}"
|
||||
end
|
||||
print_hi('Tom')
|
||||
#=> prints 'Hi, Tom' to STDOUT.
|
||||
{% endhighlight %}
|
||||
|
||||
Check out the [Jekyll docs][jekyll] for more info on how to get the most out of Jekyll. File all bugs/feature requests at [Jekyll's GitHub repo][jekyll-gh].
|
||||
|
||||
[jekyll-gh]: https://github.com/mojombo/jekyll
|
||||
[jekyll]: http://jekyllrb.com
|
|
@ -0,0 +1,189 @@
|
|||
/*****************************************************************************/
|
||||
/*
|
||||
/* Common
|
||||
/*
|
||||
/*****************************************************************************/
|
||||
|
||||
/* Global Reset */
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
html, body {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: white;
|
||||
font: 13.34px helvetica, arial, clean, sans-serif;
|
||||
*font-size: small;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-size: 100%;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #00a;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: black;
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color: #a0a;
|
||||
}
|
||||
|
||||
table {
|
||||
font-size: inherit;
|
||||
font: 100%;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
/* Home
|
||||
/*
|
||||
/*****************************************************************************/
|
||||
|
||||
ul.posts {
|
||||
list-style-type: none;
|
||||
margin-bottom: 2em;
|
||||
}
|
||||
|
||||
ul.posts li {
|
||||
line-height: 1.75em;
|
||||
}
|
||||
|
||||
ul.posts span {
|
||||
color: #aaa;
|
||||
font-family: Monaco, "Courier New", monospace;
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
/* Site
|
||||
/*
|
||||
/*****************************************************************************/
|
||||
|
||||
.site {
|
||||
font-size: 110%;
|
||||
text-align: justify;
|
||||
width: 42em;
|
||||
margin: 3em auto 2em auto;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
|
||||
.title {
|
||||
color: #a00;
|
||||
font-weight: bold;
|
||||
margin-bottom: 2em;
|
||||
}
|
||||
|
||||
.site .title a {
|
||||
color: #a00;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.site .title a:hover {
|
||||
color: black;
|
||||
}
|
||||
|
||||
.site .title a.extra {
|
||||
color: #aaa;
|
||||
text-decoration: none;
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
||||
.site .title a.extra:hover {
|
||||
color: black;
|
||||
}
|
||||
|
||||
.site .meta {
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
.site .footer {
|
||||
font-size: 80%;
|
||||
color: #666;
|
||||
border-top: 4px solid #eee;
|
||||
margin-top: 2em;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.site .footer .contact {
|
||||
float: left;
|
||||
margin-right: 3em;
|
||||
}
|
||||
|
||||
.site .footer .contact a {
|
||||
color: #8085C1;
|
||||
}
|
||||
|
||||
.site .footer .rss {
|
||||
margin-top: 1.1em;
|
||||
margin-right: -.2em;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.site .footer .rss img {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
/* Posts
|
||||
/*
|
||||
/*****************************************************************************/
|
||||
|
||||
#post {
|
||||
|
||||
}
|
||||
|
||||
/* standard */
|
||||
|
||||
#post pre {
|
||||
border: 1px solid #ddd;
|
||||
background-color: #eef;
|
||||
padding: 0 .4em;
|
||||
}
|
||||
|
||||
#post ul,
|
||||
#post ol {
|
||||
margin-left: 1.35em;
|
||||
}
|
||||
|
||||
#post code {
|
||||
border: 1px solid #ddd;
|
||||
background-color: #eef;
|
||||
font-size: 85%;
|
||||
padding: 0 .2em;
|
||||
}
|
||||
|
||||
#post pre code {
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* terminal */
|
||||
|
||||
#post pre.terminal {
|
||||
border: 1px solid black;
|
||||
background-color: #333;
|
||||
color: white;
|
||||
}
|
||||
|
||||
#post pre.terminal code {
|
||||
background-color: #333;
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
.highlight { background: #ffffff; }
|
||||
.highlight .c { color: #999988; font-style: italic } /* Comment */
|
||||
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
|
||||
.highlight .k { font-weight: bold } /* Keyword */
|
||||
.highlight .o { font-weight: bold } /* Operator */
|
||||
.highlight .cm { color: #999988; font-style: italic } /* Comment.Multiline */
|
||||
.highlight .cp { color: #999999; font-weight: bold } /* Comment.Preproc */
|
||||
.highlight .c1 { color: #999988; font-style: italic } /* Comment.Single */
|
||||
.highlight .cs { color: #999999; font-weight: bold; font-style: italic } /* Comment.Special */
|
||||
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
|
||||
.highlight .gd .x { color: #000000; background-color: #ffaaaa } /* Generic.Deleted.Specific */
|
||||
.highlight .ge { font-style: italic } /* Generic.Emph */
|
||||
.highlight .gr { color: #aa0000 } /* Generic.Error */
|
||||
.highlight .gh { color: #999999 } /* Generic.Heading */
|
||||
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
|
||||
.highlight .gi .x { color: #000000; background-color: #aaffaa } /* Generic.Inserted.Specific */
|
||||
.highlight .go { color: #888888 } /* Generic.Output */
|
||||
.highlight .gp { color: #555555 } /* Generic.Prompt */
|
||||
.highlight .gs { font-weight: bold } /* Generic.Strong */
|
||||
.highlight .gu { color: #aaaaaa } /* Generic.Subheading */
|
||||
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
|
||||
.highlight .kc { font-weight: bold } /* Keyword.Constant */
|
||||
.highlight .kd { font-weight: bold } /* Keyword.Declaration */
|
||||
.highlight .kp { font-weight: bold } /* Keyword.Pseudo */
|
||||
.highlight .kr { font-weight: bold } /* Keyword.Reserved */
|
||||
.highlight .kt { color: #445588; font-weight: bold } /* Keyword.Type */
|
||||
.highlight .m { color: #009999 } /* Literal.Number */
|
||||
.highlight .s { color: #d14 } /* Literal.String */
|
||||
.highlight .na { color: #008080 } /* Name.Attribute */
|
||||
.highlight .nb { color: #0086B3 } /* Name.Builtin */
|
||||
.highlight .nc { color: #445588; font-weight: bold } /* Name.Class */
|
||||
.highlight .no { color: #008080 } /* Name.Constant */
|
||||
.highlight .ni { color: #800080 } /* Name.Entity */
|
||||
.highlight .ne { color: #990000; font-weight: bold } /* Name.Exception */
|
||||
.highlight .nf { color: #990000; font-weight: bold } /* Name.Function */
|
||||
.highlight .nn { color: #555555 } /* Name.Namespace */
|
||||
.highlight .nt { color: #000080 } /* Name.Tag */
|
||||
.highlight .nv { color: #008080 } /* Name.Variable */
|
||||
.highlight .ow { font-weight: bold } /* Operator.Word */
|
||||
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
|
||||
.highlight .mf { color: #009999 } /* Literal.Number.Float */
|
||||
.highlight .mh { color: #009999 } /* Literal.Number.Hex */
|
||||
.highlight .mi { color: #009999 } /* Literal.Number.Integer */
|
||||
.highlight .mo { color: #009999 } /* Literal.Number.Oct */
|
||||
.highlight .sb { color: #d14 } /* Literal.String.Backtick */
|
||||
.highlight .sc { color: #d14 } /* Literal.String.Char */
|
||||
.highlight .sd { color: #d14 } /* Literal.String.Doc */
|
||||
.highlight .s2 { color: #d14 } /* Literal.String.Double */
|
||||
.highlight .se { color: #d14 } /* Literal.String.Escape */
|
||||
.highlight .sh { color: #d14 } /* Literal.String.Heredoc */
|
||||
.highlight .si { color: #d14 } /* Literal.String.Interpol */
|
||||
.highlight .sx { color: #d14 } /* Literal.String.Other */
|
||||
.highlight .sr { color: #009926 } /* Literal.String.Regex */
|
||||
.highlight .s1 { color: #d14 } /* Literal.String.Single */
|
||||
.highlight .ss { color: #990073 } /* Literal.String.Symbol */
|
||||
.highlight .bp { color: #999999 } /* Name.Builtin.Pseudo */
|
||||
.highlight .vc { color: #008080 } /* Name.Variable.Class */
|
||||
.highlight .vg { color: #008080 } /* Name.Variable.Global */
|
||||
.highlight .vi { color: #008080 } /* Name.Variable.Instance */
|
||||
.highlight .il { color: #009999 } /* Literal.Number.Integer.Long */
|
Binary file not shown.
After Width: | Height: | Size: 5.0 KiB |
|
@ -0,0 +1,13 @@
|
|||
---
|
||||
layout: default
|
||||
title: Your New Jekyll Site
|
||||
---
|
||||
|
||||
<div id="home">
|
||||
<h1>Blog Posts</h1>
|
||||
<ul class="posts">
|
||||
{% for post in site.posts %}
|
||||
<li><span>{{ post.date | date_to_string }}</span> » <a href="{{ post.url }}">{{ post.title }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
|
@ -0,0 +1,104 @@
|
|||
require 'helper'
|
||||
require 'jekyll/commands/new'
|
||||
|
||||
class TestNewCommand < Test::Unit::TestCase
|
||||
def dir_contents(path)
|
||||
Dir["#{path}/**/*"].each do |file|
|
||||
file.gsub! path, ''
|
||||
end
|
||||
end
|
||||
|
||||
def site_template
|
||||
File.expand_path("../lib/site_template", File.dirname(__FILE__))
|
||||
end
|
||||
|
||||
context 'when args contains a path' do
|
||||
setup do
|
||||
@path = 'new-site'
|
||||
@args = [@path]
|
||||
@full_path = File.expand_path(@path, Dir.pwd)
|
||||
end
|
||||
|
||||
teardown do
|
||||
FileUtils.rm_r @full_path
|
||||
end
|
||||
|
||||
should 'create a new directory' do
|
||||
assert !File.exists?(@full_path)
|
||||
capture_stdout { Jekyll::Commands::New.process(@args) }
|
||||
assert File.exists?(@full_path)
|
||||
end
|
||||
|
||||
should 'display a success message' do
|
||||
output = capture_stdout { Jekyll::Commands::New.process(@args) }
|
||||
success_message = "New jekyll site installed in #{@full_path}.\n"
|
||||
assert_equal success_message, output
|
||||
end
|
||||
|
||||
should 'copy the static files in site template to the new directory' do
|
||||
static_template_files = dir_contents(site_template).reject do |f|
|
||||
File.extname(f) == '.erb'
|
||||
end
|
||||
|
||||
capture_stdout { Jekyll::Commands::New.process(@args) }
|
||||
|
||||
new_site_files = dir_contents(@full_path).reject do |f|
|
||||
File.extname(f) == '.markdown'
|
||||
end
|
||||
|
||||
assert_same_elements static_template_files, new_site_files
|
||||
end
|
||||
|
||||
should 'process any ERB files' do
|
||||
erb_template_files = dir_contents(site_template).select do |f|
|
||||
File.extname(f) == '.erb'
|
||||
end
|
||||
|
||||
stubbed_date = '2013-01-01'
|
||||
stub.instance_of(Time).strftime { stubbed_date }
|
||||
|
||||
erb_template_files.each do |f|
|
||||
f.chomp! '.erb'
|
||||
f.gsub! '0000-00-00', stubbed_date
|
||||
end
|
||||
|
||||
capture_stdout { Jekyll::Commands::New.process(@args) }
|
||||
|
||||
new_site_files = dir_contents(@full_path).select do |f|
|
||||
erb_template_files.include? f
|
||||
end
|
||||
|
||||
assert_same_elements erb_template_files, new_site_files
|
||||
end
|
||||
end
|
||||
|
||||
context 'when multiple args are given' do
|
||||
setup do
|
||||
@site_name_with_spaces = 'new site name'
|
||||
@multiple_args = @site_name_with_spaces.split
|
||||
end
|
||||
|
||||
teardown do
|
||||
FileUtils.rm_r File.expand_path(@site_name_with_spaces, Dir.pwd)
|
||||
end
|
||||
|
||||
should 'create a new directory' do
|
||||
assert !File.exists?(@site_name_with_spaces)
|
||||
capture_stdout { Jekyll::Commands::New.process(@multiple_args) }
|
||||
assert File.exists?(@site_name_with_spaces)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when no args are given' do
|
||||
setup do
|
||||
@empty_args = []
|
||||
end
|
||||
|
||||
should 'raise an ArgumentError' do
|
||||
exception = assert_raise ArgumentError do
|
||||
Jekyll::Commands::New.process(@empty_args)
|
||||
end
|
||||
assert_equal 'You must specify a path.', exception.message
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue