serif 0.4 → 0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile.lock +29 -14
- data/README.md +28 -14
- data/bin/serif +2 -69
- data/lib/serif.rb +1 -0
- data/lib/serif/admin_server.rb +55 -26
- data/lib/serif/commands.rb +150 -0
- data/lib/serif/content_file.rb +4 -0
- data/lib/serif/draft.rb +24 -2
- data/lib/serif/errors.rb +10 -0
- data/lib/serif/post.rb +4 -3
- data/lib/serif/site.rb +73 -4
- data/rakefile +10 -0
- data/serif.gemspec +5 -3
- data/statics/skeleton/_layouts/default.html +1 -1
- data/statics/templates/admin/bookmarks.liquid +17 -13
- data/statics/templates/admin/edit_draft.liquid +1 -1
- data/statics/templates/admin/edit_post.liquid +1 -1
- data/statics/templates/admin/index.liquid +2 -2
- data/statics/templates/admin/layout.liquid +16 -0
- data/test/commands_spec.rb +77 -0
- data/test/content_file_spec.rb +32 -1
- data/test/draft_spec.rb +50 -3
- data/test/post_spec.rb +31 -2
- data/test/site_dir/_layouts/default.html +2 -0
- data/test/site_dir/_site/archive.html +2 -0
- data/test/site_dir/_site/drafts/another-sample-draft/{481da12b79709bfa0547fa9b5754c9506fbed29afd0334e07a8c95e76850.html → add25848a94509103cb492c47e3a04b7b2a56299de207155fbffec42dc4b.html} +5 -2
- data/test/site_dir/_site/drafts/sample-draft/{a986a62ad5f6edd1fcac3d08f5b461b92bcb667a2af69505230c291d405c.html → 0b6fc164b8534d5d5a9fcfc5c709265d33f1577cd0fe2f4e23042e92f0c1.html} +5 -2
- data/test/site_dir/_site/index.html +2 -0
- data/test/site_dir/_site/page-header-but-no-layout.html +2 -0
- data/test/site_dir/_site/test-archive/2012/11.html +2 -0
- data/test/site_dir/_site/test-archive/2012/12.html +2 -0
- data/test/site_dir/_site/test-archive/2013/01.html +2 -0
- data/test/site_dir/_site/test-archive/2013/03.html +2 -0
- data/test/site_dir/_site/test-archive/2399/01.html +2 -0
- data/test/site_dir/_site/test-archive/2400/01.html +2 -0
- data/test/site_dir/_site/test-blog/final-post.html +4 -1
- data/test/site_dir/_site/test-blog/penultimate-post.html +4 -1
- data/test/site_dir/_site/test-blog/post-to-be-published-on-generate.html +4 -1
- data/test/site_dir/_site/test-blog/post-with-custom-layout.html +1 -0
- data/test/site_dir/_site/test-blog/sample-post.html +4 -1
- data/test/site_dir/_site/test-blog/second-post.html +4 -1
- data/test/site_dir/_site/test-smarty-filter.html +2 -0
- data/test/site_dir/_templates/post.html +1 -0
- data/test/site_dir/_trash/1364747613-autopublish-draft +5 -0
- data/test/site_dir/_trash/{1363633154-test-draft → 1364747613-test-draft} +1 -1
- data/test/site_generation_spec.rb +40 -9
- data/test/site_spec.rb +63 -0
- data/test/test_helper.rb +9 -0
- metadata +46 -10
- data/test/site_dir/_trash/1363633154-autopublish-draft +0 -5
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
serif (0.
|
4
|
+
serif (0.4)
|
5
5
|
liquid (~> 2.4)
|
6
6
|
nokogiri (~> 1.5)
|
7
7
|
rack (~> 1.0)
|
@@ -15,37 +15,50 @@ PATH
|
|
15
15
|
GEM
|
16
16
|
remote: http://rubygems.org/
|
17
17
|
specs:
|
18
|
-
|
18
|
+
colorize (0.5.8)
|
19
|
+
coveralls (0.6.3)
|
20
|
+
colorize
|
21
|
+
multi_json (~> 1.3)
|
22
|
+
rest-client
|
23
|
+
simplecov (>= 0.7)
|
24
|
+
thor
|
25
|
+
diff-lcs (1.2.2)
|
26
|
+
json (1.7.7)
|
19
27
|
liquid (2.5.0)
|
20
|
-
|
21
|
-
|
28
|
+
mime-types (1.22)
|
29
|
+
multi_json (1.7.2)
|
30
|
+
nokogiri (1.5.9)
|
22
31
|
rack (1.5.2)
|
23
32
|
rack-protection (1.5.0)
|
24
33
|
rack
|
25
34
|
rake (0.9.6)
|
35
|
+
rdoc (4.0.1)
|
36
|
+
json (~> 1.4)
|
26
37
|
redcarpet (2.2.2)
|
27
38
|
redhead (0.0.8)
|
39
|
+
rest-client (1.6.7)
|
40
|
+
mime-types (>= 1.16)
|
28
41
|
reverse_markdown (0.4.4)
|
29
42
|
nokogiri
|
30
43
|
rouge (0.3.2)
|
31
44
|
thor
|
32
|
-
rspec (2.
|
33
|
-
rspec-core (~> 2.
|
34
|
-
rspec-expectations (~> 2.
|
35
|
-
rspec-mocks (~> 2.
|
36
|
-
rspec-core (2.
|
37
|
-
rspec-expectations (2.
|
38
|
-
diff-lcs (
|
39
|
-
rspec-mocks (2.
|
45
|
+
rspec (2.13.0)
|
46
|
+
rspec-core (~> 2.13.0)
|
47
|
+
rspec-expectations (~> 2.13.0)
|
48
|
+
rspec-mocks (~> 2.13.0)
|
49
|
+
rspec-core (2.13.1)
|
50
|
+
rspec-expectations (2.13.0)
|
51
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
52
|
+
rspec-mocks (2.13.0)
|
40
53
|
simplecov (0.7.1)
|
41
54
|
multi_json (~> 1.0)
|
42
55
|
simplecov-html (~> 0.7.1)
|
43
56
|
simplecov-html (0.7.1)
|
44
|
-
sinatra (1.4.
|
57
|
+
sinatra (1.4.2)
|
45
58
|
rack (~> 1.5, >= 1.5.2)
|
46
59
|
rack-protection (~> 1.4)
|
47
60
|
tilt (~> 1.3, >= 1.3.4)
|
48
|
-
thor (0.
|
61
|
+
thor (0.18.1)
|
49
62
|
tilt (1.3.6)
|
50
63
|
timecop (0.6.1)
|
51
64
|
timeout_cache (0.0.2)
|
@@ -54,7 +67,9 @@ PLATFORMS
|
|
54
67
|
ruby
|
55
68
|
|
56
69
|
DEPENDENCIES
|
70
|
+
coveralls
|
57
71
|
rake (~> 0.9)
|
72
|
+
rdoc (~> 4.0.0)
|
58
73
|
rspec (~> 2.5)
|
59
74
|
serif!
|
60
75
|
simplecov (~> 0.7)
|
data/README.md
CHANGED
@@ -1,10 +1,12 @@
|
|
1
1
|
# Serif
|
2
2
|
|
3
|
-
[![Build Status](https://travis-ci.org/aprescott/serif.png?branch=master)](https://travis-ci.org/aprescott/serif)
|
3
|
+
[![Build Status](https://travis-ci.org/aprescott/serif.png?branch=master)](https://travis-ci.org/aprescott/serif) [![Code Climate](https://codeclimate.com/github/aprescott/serif.png)](https://codeclimate.com/github/aprescott/serif) [![Coverage Status](https://coveralls.io/repos/aprescott/serif/badge.png?branch=master)](https://coveralls.io/r/aprescott/serif)
|
4
4
|
|
5
|
-
Serif is a
|
5
|
+
Serif is a static site generator and blogging system powered by markdown files and an optional admin interface complete with drag-and-drop image uploading. ([Check out the simple video demo](https://docs.google.com/open?id=0BxPQpxGSOOyKS1J4MmlnM3JIaXM).)
|
6
6
|
|
7
|
-
|
7
|
+
Serif releases you from managing a file system so you can focus on writing content.
|
8
|
+
|
9
|
+
Having problems with Serif? [Open an issue on GitHub](https://github.com/aprescott/serif/issues), use the [Serif Google Group](https://groups.google.com/forum/#!forum/serif-rb), or [join the Freenode#serif IRC channel](irc://irc.freenode.net/serif).
|
8
10
|
|
9
11
|
## First time use
|
10
12
|
|
@@ -177,9 +179,24 @@ Something something.
|
|
177
179
|
End of the post
|
178
180
|
```
|
179
181
|
|
182
|
+
### Headers
|
183
|
+
|
180
184
|
The headers are similar to Jekyll's YAML front matter, but here there are no formatting requirements beyond `Key: value` pairs. Header names are case-insensitive (so `title` is the same as `Title`), but values are not.
|
181
185
|
|
182
|
-
|
186
|
+
File headers like `Title: Some title` can contain any header, but certain headers have special meaning in Serif.
|
187
|
+
|
188
|
+
Header name | Meaning
|
189
|
+
----------- |:-------
|
190
|
+
`Created` | For a post, timestamp for when it was first published. Must be a string that Ruby's `Time` class can parse. Means nothing for drafts.
|
191
|
+
`Updated` | For a post, timestamp for when it was last updated. Must be a string that Ruby's `Time` class can parse. Means nothing for drafts.
|
192
|
+
`Title` | Title for the draft or post.
|
193
|
+
`Update` | For a post, When given the value of `now` (i.e., `Update: now`), the `Updated` timestamp will be updated on the next site generation. Means nothing for drafts.
|
194
|
+
`Publish` | For a draft, when given the value of `now` (i.e., `Publish: now`), the draft will be published on the next site generation (and the `Created` set appropriately). Means nothing for a post.
|
195
|
+
`Permalink` | For a post, overrides the default permalink value defined in `_config.yml`. **Note that this is interpolated**, so `:title` in the permalink value will be replaced according to regular permalink rules. Means nothing for a draft.
|
196
|
+
|
197
|
+
Note that while it is possible for you to manually handle timestamp values, it is recommended that you rely on using the value of `now` for `Update` and `Publish`.
|
198
|
+
|
199
|
+
If you change the `permalink` value for a published post, you will break any inbound URLs as well as, e.g., any feeds that rely on the URL as a unique persistent ID.
|
183
200
|
|
184
201
|
## `_templates`
|
185
202
|
|
@@ -217,6 +234,8 @@ Placeholder | Value
|
|
217
234
|
`:month` | Month as given in the filename, e.g., "01"
|
218
235
|
`:day` | Day as given in the filename, e.g., "28"
|
219
236
|
|
237
|
+
<b>NOTE</b>: if you change the permalink value, you will break existing URLs for published posts, in addition to, e.g., any feed ID values that depend on the post URL never changing.
|
238
|
+
|
220
239
|
### Admin drag-and-drop upload path
|
221
240
|
|
222
241
|
The `image_upload_path` configuration setting is an _absolute path_ and will be relative to the base directory of your site, used in the admin interface to control where files are sent. The default value is `/images/:timestamp_:name`. Similar to permalinks, the following placeholders are available:
|
@@ -283,7 +302,7 @@ On the next site generation (`serif generate`) this draft will be automatically
|
|
283
302
|
|
284
303
|
# Updating posts
|
285
304
|
|
286
|
-
When you update a
|
305
|
+
When you update a post, you need to remember to change the updated time. As luck would have it, Serif takes care of timestamps for you! Just use a header of `update: now` at the top of your published post after making your changes:
|
287
306
|
|
288
307
|
```
|
289
308
|
title: My blog post
|
@@ -470,6 +489,7 @@ These should be available in any template:
|
|
470
489
|
* `{{ site.latest_update_time }}` --- a [Ruby `Time`](http://ruby-doc.org/core/Time.html) instance for the latest time that any post was updated. Useful for RSS/Atom feeds.
|
471
490
|
* `{{ site.archives }}` --- a nested hash structure that groups posts by month. See above for how to use it.
|
472
491
|
* `{{ draft_preview }}` -- Set to true if this is part of generating a draft preview.
|
492
|
+
* `{{ post_page }}` -- Set to true if this is part of generating a regular published post.
|
473
493
|
|
474
494
|
## Post variables
|
475
495
|
|
@@ -483,6 +503,7 @@ Name | Value
|
|
483
503
|
`post.created` | A [Ruby `Time`](http://ruby-doc.org/core/Time.html) instance for the time the post was first published.
|
484
504
|
`post.updated` | A [Ruby `Time`](http://ruby-doc.org/core/Time.html) instance for the time the post was last updated.
|
485
505
|
`post.content` | The raw post content. Example use: `{{ post.content | markdown }}`.
|
506
|
+
`post.foo` | The value of the `Foo` header, e.g., if `Foo: my special header` is in the source file, `post.foo` is `my special header`. All headers are merged into the `{{ post }}` variable for you to use in templates.
|
486
507
|
|
487
508
|
## Variables available within post templates
|
488
509
|
|
@@ -511,6 +532,7 @@ Variable | Value
|
|
511
532
|
* `./bin/serif {dev,admin,generate}` to run Serif commands.
|
512
533
|
* `rake test` to run the tests.
|
513
534
|
* Unit tests are written in RSpec.
|
535
|
+
* `rake docs` will generate HTML documentation in `docs/`. Open `docs/index.html` in a browser to start.
|
514
536
|
|
515
537
|
## Directory structure
|
516
538
|
|
@@ -519,15 +541,7 @@ Variable | Value
|
|
519
541
|
|
520
542
|
# Changes and what's new
|
521
543
|
|
522
|
-
|
523
|
-
|
524
|
-
## v0.3.3
|
525
|
-
|
526
|
-
* Allow drag-and-drop to work on posts as well as drafts. (9ea3bebf)
|
527
|
-
* `serif new` no longer creates a sample published post (#37) and generates immediately. (#39)
|
528
|
-
* Pygments.rb is replaced with Rouge for code highlighting. (#34)
|
529
|
-
|
530
|
-
See `CHANGELOG` for more.
|
544
|
+
See `CHANGELOG`.
|
531
545
|
|
532
546
|
# Planned features
|
533
547
|
|
data/bin/serif
CHANGED
@@ -2,73 +2,6 @@
|
|
2
2
|
|
3
3
|
$:.unshift File.expand_path(File.join(File.dirname(__FILE__), "..", "lib"))
|
4
4
|
|
5
|
-
require "
|
5
|
+
require "serif/commands"
|
6
6
|
|
7
|
-
|
8
|
-
# need to cd to the directory before requiring the admin
|
9
|
-
# server, because otherwise Dir.pwd won't be right when
|
10
|
-
# the admin server class is defined at require time.
|
11
|
-
FileUtils.cd(source_dir)
|
12
|
-
require "serif"
|
13
|
-
require "serif/admin_server"
|
14
|
-
|
15
|
-
server = Serif::AdminServer.new(source_dir)
|
16
|
-
server.start
|
17
|
-
end
|
18
|
-
|
19
|
-
def initialize_dev_server(source_dir)
|
20
|
-
FileUtils.cd(source_dir)
|
21
|
-
require "serif"
|
22
|
-
require "serif/server"
|
23
|
-
|
24
|
-
server = Serif::DevelopmentServer.new(source_dir)
|
25
|
-
server.start
|
26
|
-
end
|
27
|
-
|
28
|
-
def generate_site(source_dir)
|
29
|
-
require "serif"
|
30
|
-
|
31
|
-
site = Serif::Site.new(source_dir)
|
32
|
-
site.generate
|
33
|
-
end
|
34
|
-
|
35
|
-
def verify_directory(dir)
|
36
|
-
unless Dir.exist?(dir)
|
37
|
-
puts "No such directory: #{dir}'"
|
38
|
-
exit 1
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
def produce_skeleton(dir)
|
43
|
-
if !Dir[File.join(dir, "*")].empty?
|
44
|
-
abort "Directory is not empty."
|
45
|
-
end
|
46
|
-
|
47
|
-
FileUtils.cd(File.join(File.dirname(__FILE__), "..", "statics", "skeleton"))
|
48
|
-
files = Dir["*"]
|
49
|
-
files.each do |f|
|
50
|
-
FileUtils.cp_r(f, dir, verbose: true)
|
51
|
-
end
|
52
|
-
|
53
|
-
generate_site(dir)
|
54
|
-
|
55
|
-
puts
|
56
|
-
puts "*** NOTE ***"
|
57
|
-
puts
|
58
|
-
puts "You should now edit the username and password in _config.yml"
|
59
|
-
puts
|
60
|
-
end
|
61
|
-
|
62
|
-
command = ARGV.shift
|
63
|
-
args = ARGV
|
64
|
-
|
65
|
-
case command
|
66
|
-
when "admin"
|
67
|
-
initialize_admin_server(Dir.pwd)
|
68
|
-
when "generate"
|
69
|
-
generate_site(Dir.pwd)
|
70
|
-
when "dev"
|
71
|
-
initialize_dev_server(Dir.pwd)
|
72
|
-
when "new"
|
73
|
-
produce_skeleton(Dir.pwd)
|
74
|
-
end
|
7
|
+
Serif::Commands.new(ARGV).process
|
data/lib/serif.rb
CHANGED
data/lib/serif/admin_server.rb
CHANGED
@@ -19,6 +19,10 @@ class AdminServer
|
|
19
19
|
[username, password] == [site.config.admin_username, site.config.admin_password]
|
20
20
|
end
|
21
21
|
|
22
|
+
before do
|
23
|
+
@conflicts = site.conflicts
|
24
|
+
end
|
25
|
+
|
22
26
|
# multiple public folders??
|
23
27
|
get "/admin/js/:file" do |file|
|
24
28
|
assets_dir = File.join(File.dirname(__FILE__), "..", "..", "statics", "assets", "js")
|
@@ -34,7 +38,7 @@ class AdminServer
|
|
34
38
|
posts = site.posts.sort_by { |p| p.created }.reverse
|
35
39
|
drafts = site.drafts.sort_by { |p| File.mtime(p.path) }.reverse
|
36
40
|
|
37
|
-
liquid :index, locals: { posts: posts, drafts: drafts }
|
41
|
+
liquid :index, locals: { conflicts: @conflicts, posts: posts, drafts: drafts }
|
38
42
|
end
|
39
43
|
|
40
44
|
get "/admin/edit/?" do
|
@@ -42,7 +46,7 @@ class AdminServer
|
|
42
46
|
end
|
43
47
|
|
44
48
|
get "/admin/bookmarks" do
|
45
|
-
liquid :bookmarks, locals: {
|
49
|
+
liquid :bookmarks, locals: { conflicts: @conflicts }
|
46
50
|
end
|
47
51
|
|
48
52
|
get "/admin/quick-draft" do
|
@@ -76,21 +80,36 @@ class AdminServer
|
|
76
80
|
draft = Draft.new(site)
|
77
81
|
draft.title = title
|
78
82
|
draft.slug = slug
|
79
|
-
draft.save(markdown)
|
80
83
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
84
|
+
# if the draft itself has no conflict, save it,
|
85
|
+
# otherwise show the new draft page with an error.
|
86
|
+
#
|
87
|
+
# if, after saving the draft because of no conflict,
|
88
|
+
# there is actually an overall site conflict, then
|
89
|
+
# keep on trucking so it doesn't interrupt the user.
|
90
|
+
if site.conflicts(draft)
|
91
|
+
liquid :new_draft, locals: { conflicts: @conflicts, images_path: site.config.image_upload_path.gsub(/"/, '\"'), post: draft, error_message: "There is a conflict on this draft." }
|
85
92
|
else
|
86
|
-
|
93
|
+
draft.save(markdown)
|
94
|
+
|
95
|
+
begin
|
96
|
+
site.generate
|
97
|
+
rescue PostConflictError => e
|
98
|
+
puts "Site has conflicts, skipping generation for now."
|
99
|
+
end
|
100
|
+
|
101
|
+
if params[:edit] == "1"
|
102
|
+
redirect to("/admin/edit/drafts/#{slug}")
|
103
|
+
else
|
104
|
+
redirect to(url)
|
105
|
+
end
|
87
106
|
end
|
88
107
|
end
|
89
108
|
|
90
109
|
get "/admin/new/draft" do
|
91
110
|
content = Draft.new(site)
|
92
111
|
autofocus = "slug"
|
93
|
-
liquid :new_draft, locals: { images_path: site.config.image_upload_path.gsub(/"/, '\"'), post: content, autofocus: autofocus }
|
112
|
+
liquid :new_draft, locals: { conflicts: @conflicts, images_path: site.config.image_upload_path.gsub(/"/, '\"'), post: content, autofocus: autofocus }
|
94
113
|
end
|
95
114
|
|
96
115
|
post "/admin/new/draft" do
|
@@ -109,13 +128,18 @@ class AdminServer
|
|
109
128
|
autofocus = "title" unless params[:title]
|
110
129
|
autofocus = "slug" unless params[:slug]
|
111
130
|
|
112
|
-
liquid :new_draft, locals: { images_path: site.config.image_upload_path.gsub(/"/, '\"'), error_message: error_message, post: content, autofocus: autofocus }
|
131
|
+
liquid :new_draft, locals: { conflicts: @conflicts, images_path: site.config.image_upload_path.gsub(/"/, '\"'), error_message: error_message, post: content, autofocus: autofocus }
|
113
132
|
else
|
114
133
|
if Draft.exist?(site, params[:slug])
|
115
|
-
|
134
|
+
error_message = "Draft already eixsts with the given slug #{params[:slug]}."
|
135
|
+
liquid :new_draft, locals: { conflicts: @conflicts, images_path: site.config.image_upload_path.gsub(/"/, '\"'), error_message: error_message, post: content, autofocus: autofocus }
|
116
136
|
else
|
117
137
|
content.save(params[:markdown])
|
118
|
-
|
138
|
+
begin
|
139
|
+
site.generate
|
140
|
+
rescue PostConflictError => e
|
141
|
+
puts "Cannot generate. Skipping for now."
|
142
|
+
end
|
119
143
|
redirect to("/admin")
|
120
144
|
end
|
121
145
|
end
|
@@ -155,7 +179,10 @@ class AdminServer
|
|
155
179
|
error_message = "You must pick a URL to use"
|
156
180
|
end
|
157
181
|
|
158
|
-
liquid :edit_draft, locals: { images_path: site.config.image_upload_path.gsub(/"/, '\"'), error_message: error_message, post: content, private_url: site.private_url(content) }
|
182
|
+
liquid :edit_draft, locals: { conflicts: @conflicts, images_path: site.config.image_upload_path.gsub(/"/, '\"'), error_message: error_message, post: content, private_url: site.private_url(content) }
|
183
|
+
elsif (conflicts = site.conflicts)
|
184
|
+
error_message = "The site has a conflict and cannot be generated."
|
185
|
+
liquid :edit_draft, locals: { conflicts: @conflicts, images_path: site.config.image_upload_path.gsub(/"/, '\"'), error_message: error_message, post: content, private_url: site.private_url(content) }
|
159
186
|
else
|
160
187
|
content.save(params[:markdown])
|
161
188
|
|
@@ -172,7 +199,7 @@ class AdminServer
|
|
172
199
|
end
|
173
200
|
|
174
201
|
post "/admin/edit/posts" do
|
175
|
-
content = Post.
|
202
|
+
content = Post.from_basename(site, params[:original_basename])
|
176
203
|
|
177
204
|
params[:markdown] = params[:markdown].strip
|
178
205
|
params[:title] = params[:title].strip
|
@@ -183,7 +210,10 @@ class AdminServer
|
|
183
210
|
error_message = "Content must not be blank." if params[:markdown].empty?
|
184
211
|
error_message = "Title must not be blank." if params[:title].empty?
|
185
212
|
|
186
|
-
liquid :edit_post, locals: { images_path: site.config.image_upload_path.gsub(/"/, '\"'), error_message: error_message, post: content }
|
213
|
+
liquid :edit_post, locals: { conflicts: @conflicts, images_path: site.config.image_upload_path.gsub(/"/, '\"'), error_message: error_message, post: content }
|
214
|
+
elsif (conflicts = site.conflicts)
|
215
|
+
error_message = "The site has a conflict and cannot be generated."
|
216
|
+
liquid :edit_post, locals: { conflicts: @conflicts, images_path: site.config.image_upload_path.gsub(/"/, '\"'), error_message: error_message, post: content }
|
187
217
|
else
|
188
218
|
content.save(params[:markdown])
|
189
219
|
site.generate
|
@@ -192,19 +222,18 @@ class AdminServer
|
|
192
222
|
end
|
193
223
|
end
|
194
224
|
|
195
|
-
get "/admin/edit/:
|
225
|
+
get "/admin/edit/posts/:basename" do
|
226
|
+
redirect to("/admin") unless params[:basename]
|
227
|
+
|
228
|
+
content = Post.from_basename(site, params[:basename])
|
229
|
+
liquid :edit_post, locals: { conflicts: @conflicts, images_path: site.config.image_upload_path.gsub(/"/, '\"'), post: content, autofocus: "markdown" }
|
230
|
+
end
|
231
|
+
|
232
|
+
get "/admin/edit/drafts/:slug" do
|
196
233
|
redirect to("/admin") unless params[:slug]
|
197
234
|
|
198
|
-
|
199
|
-
|
200
|
-
liquid :edit_post, locals: { images_path: site.config.image_upload_path.gsub(/"/, '\"'), post: content, autofocus: "markdown" }
|
201
|
-
elsif params[:type] == "drafts"
|
202
|
-
content = Draft.from_slug(site, params[:slug])
|
203
|
-
liquid :edit_draft, locals: { images_path: site.config.image_upload_path.gsub(/"/, '\"'), post: content, autofocus: "markdown", private_url: site.private_url(content) }
|
204
|
-
else
|
205
|
-
response.status = 404
|
206
|
-
return "Nope"
|
207
|
-
end
|
235
|
+
content = Draft.from_slug(site, params[:slug])
|
236
|
+
liquid :edit_draft, locals: { conflicts: @conflicts, images_path: site.config.image_upload_path.gsub(/"/, '\"'), post: content, autofocus: "markdown", private_url: site.private_url(content) }
|
208
237
|
end
|
209
238
|
|
210
239
|
post "/admin/delete/?" do
|
@@ -0,0 +1,150 @@
|
|
1
|
+
require "fileutils"
|
2
|
+
require "serif"
|
3
|
+
require "serif/server"
|
4
|
+
|
5
|
+
module Serif
|
6
|
+
class Commands
|
7
|
+
def initialize(argv)
|
8
|
+
@argv = argv.dup
|
9
|
+
end
|
10
|
+
|
11
|
+
def process
|
12
|
+
command = @argv.shift
|
13
|
+
case command
|
14
|
+
when "-h", "--help", nil
|
15
|
+
print_help
|
16
|
+
exit 0
|
17
|
+
when "admin"
|
18
|
+
initialize_admin_server(Dir.pwd)
|
19
|
+
when "generate"
|
20
|
+
generate_site(Dir.pwd)
|
21
|
+
when "dev"
|
22
|
+
initialize_dev_server(Dir.pwd)
|
23
|
+
when "new"
|
24
|
+
produce_skeleton(Dir.pwd)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def initialize_admin_server(source_dir)
|
29
|
+
# need to cd to the directory before requiring the admin
|
30
|
+
# server, because otherwise Dir.pwd won't be right when
|
31
|
+
# the admin server class is defined at require time.
|
32
|
+
FileUtils.cd(source_dir)
|
33
|
+
require "serif/admin_server"
|
34
|
+
|
35
|
+
server = Serif::AdminServer.new(source_dir)
|
36
|
+
server.start
|
37
|
+
end
|
38
|
+
|
39
|
+
def initialize_dev_server(source_dir)
|
40
|
+
FileUtils.cd(source_dir)
|
41
|
+
|
42
|
+
server = Serif::DevelopmentServer.new(source_dir)
|
43
|
+
server.start
|
44
|
+
end
|
45
|
+
|
46
|
+
def generate_site(source_dir)
|
47
|
+
|
48
|
+
site = Serif::Site.new(source_dir)
|
49
|
+
|
50
|
+
begin
|
51
|
+
site.generate
|
52
|
+
rescue Serif::PostConflictError => e
|
53
|
+
puts "Error! Unable to generate because there is a conflict."
|
54
|
+
puts
|
55
|
+
puts "Conflicts at:"
|
56
|
+
puts
|
57
|
+
|
58
|
+
site.conflicts.each do |url, ary|
|
59
|
+
puts url
|
60
|
+
ary.each do |e|
|
61
|
+
puts "\t#{e.path}"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
exit 1
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def verify_directory(dir)
|
70
|
+
unless Dir.exist?(dir)
|
71
|
+
puts "No such directory: #{dir}'"
|
72
|
+
exit 1
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def produce_skeleton(dir)
|
77
|
+
if !Dir[File.join(dir, "*")].empty?
|
78
|
+
abort "Directory is not empty."
|
79
|
+
end
|
80
|
+
|
81
|
+
FileUtils.cd(File.join(File.dirname(__FILE__), "..", "..", "statics", "skeleton"))
|
82
|
+
files = Dir["*"]
|
83
|
+
files.each do |f|
|
84
|
+
FileUtils.cp_r(f, dir, verbose: true)
|
85
|
+
end
|
86
|
+
|
87
|
+
generate_site(dir)
|
88
|
+
|
89
|
+
puts
|
90
|
+
puts "*** NOTE ***"
|
91
|
+
puts
|
92
|
+
puts "You should now edit the username and password in _config.yml"
|
93
|
+
puts
|
94
|
+
end
|
95
|
+
|
96
|
+
def print_help
|
97
|
+
puts <<-END_HELP
|
98
|
+
USAGE
|
99
|
+
|
100
|
+
serif [-h | --help]
|
101
|
+
serif [COMMAND]
|
102
|
+
|
103
|
+
OPTIONS
|
104
|
+
|
105
|
+
-h, --help Display this help message and exit immediately.
|
106
|
+
|
107
|
+
COMMANDS
|
108
|
+
|
109
|
+
serif generate Generate the site in the current directory.
|
110
|
+
|
111
|
+
serif new Create a site skeleton to get started. Will
|
112
|
+
only run if the current directory is empty.
|
113
|
+
|
114
|
+
serif admin Start the admin server on localhost:4567.
|
115
|
+
|
116
|
+
serif dev Start a simple dev server on localhost:8000.
|
117
|
+
Serves up the generated static files, but loads
|
118
|
+
some files (like CSS) from source (instead of
|
119
|
+
out of the _site/ directory).
|
120
|
+
|
121
|
+
ENVIRONMENT VARIABLES
|
122
|
+
|
123
|
+
ENV Set to 'production' if the command is being run
|
124
|
+
as part of serving up a live site.
|
125
|
+
|
126
|
+
$ ENV=production serif generate
|
127
|
+
|
128
|
+
$ ENV=production serif admin
|
129
|
+
|
130
|
+
Note that this by and large doesn't change much,
|
131
|
+
but in future it may provide extra features.
|
132
|
+
|
133
|
+
The main benefit is that the `file_digest` tag
|
134
|
+
will return a hex digest of the given file's
|
135
|
+
contents only when ENV is set to production.
|
136
|
+
|
137
|
+
EXAMPLES
|
138
|
+
|
139
|
+
$ serif generate
|
140
|
+
|
141
|
+
Generate the site.
|
142
|
+
|
143
|
+
$ serif admin
|
144
|
+
|
145
|
+
Start the admin server on localhost:4567.
|
146
|
+
|
147
|
+
END_HELP
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|