schreihals 0.0.2 → 0.0.3
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.
- data/.gitignore +1 -0
- data/.watchr +14 -0
- data/README.md +13 -1
- data/Rakefile +9 -4
- data/bin/schreihals +5 -0
- data/example/Gemfile +0 -4
- data/lib/schreihals.rb +13 -140
- data/lib/schreihals/actions.rb +45 -0
- data/lib/schreihals/app.rb +73 -0
- data/lib/schreihals/cli.rb +42 -0
- data/lib/schreihals/document.rb +52 -0
- data/lib/schreihals/helpers.rb +38 -0
- data/lib/schreihals/post.rb +74 -0
- data/lib/schreihals/static.rb +17 -0
- data/lib/schreihals/version.rb +1 -1
- data/lib/templates/first-post.md.tt +1 -0
- data/lib/templates/new-post.md.tt +13 -0
- data/lib/templates/new_blog/.gitignore +5 -0
- data/lib/templates/new_blog/Gemfile +3 -0
- data/lib/templates/new_blog/config.ru.tt +14 -0
- data/lib/templates/new_blog/posts/.gitkeep +0 -0
- data/lib/templates/new_blog/public/media/.gitkeep +0 -0
- data/lib/views/404.haml +3 -4
- data/lib/views/blog.scss +1 -0
- data/lib/views/index.haml +2 -3
- data/lib/views/layout.haml +13 -9
- data/lib/views/partials/_gauges.haml +12 -0
- data/lib/views/partials/_post.haml +10 -2
- data/lib/views/post.haml +2 -5
- data/lib/views/schreihals.scss +24 -12
- data/schreihals.gemspec +14 -5
- data/test/app_test.rb +68 -0
- data/test/document_test.rb +41 -0
- data/test/files/simple_document.md +7 -0
- data/test/posts/2011-12-23-first-post.md +8 -0
- data/test/posts/2011-12-24-second-post.md +8 -0
- data/test/posts/static-page.md +5 -0
- data/test/test_helper.rb +63 -0
- metadata +172 -43
- data/.rspec +0 -2
- data/spec/spec_helper.rb +0 -7
@@ -0,0 +1,38 @@
|
|
1
|
+
module Schreihals
|
2
|
+
module Helpers
|
3
|
+
def find_template(views, name, engine, &block)
|
4
|
+
Array(views).each { |v| super(v, name, engine, &block) }
|
5
|
+
end
|
6
|
+
|
7
|
+
def partial(thing, locals = {})
|
8
|
+
name = case thing
|
9
|
+
when String then thing
|
10
|
+
else thing.class.to_s.demodulize.underscore
|
11
|
+
end
|
12
|
+
|
13
|
+
haml :"partials/_#{name}", :locals => { name.to_sym => thing }.merge(locals)
|
14
|
+
end
|
15
|
+
|
16
|
+
def set_page_title(title)
|
17
|
+
@page_title = title
|
18
|
+
end
|
19
|
+
|
20
|
+
def link_to(title, thing)
|
21
|
+
haml "%a{href: '#{url_for thing}'} #{title}"
|
22
|
+
end
|
23
|
+
|
24
|
+
def url_for(thing, options = {})
|
25
|
+
url = thing.respond_to?(:to_url) ? thing.to_url : thing.to_s
|
26
|
+
url = "#{settings.blog_url}#{url}" if options[:absolute]
|
27
|
+
url
|
28
|
+
end
|
29
|
+
|
30
|
+
def show_disqus?
|
31
|
+
settings.disqus_name.present?
|
32
|
+
end
|
33
|
+
|
34
|
+
def production?
|
35
|
+
settings.environment.to_sym == :production
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'tilt'
|
2
|
+
|
3
|
+
module Schreihals
|
4
|
+
class Post < Document
|
5
|
+
def initialize(*args)
|
6
|
+
super
|
7
|
+
self.attributes = {
|
8
|
+
'disqus' => true,
|
9
|
+
'status' => 'published',
|
10
|
+
'summary' => nil,
|
11
|
+
'link' => nil,
|
12
|
+
'read_more' => nil,
|
13
|
+
'date' => nil,
|
14
|
+
'title' => nil,
|
15
|
+
'slug' => nil,
|
16
|
+
'disqus_identifier' => file_name
|
17
|
+
}.merge(attributes)
|
18
|
+
|
19
|
+
# extract date and slug from file name, if possible
|
20
|
+
if file_name_without_extension =~ /^(\d{4}-\d{1,2}-\d{1,2})-?(.+)$/
|
21
|
+
attributes['date'] ||= Date.parse($1)
|
22
|
+
attributes['slug'] ||= $2
|
23
|
+
else
|
24
|
+
attributes['slug'] ||= file_name_without_extension
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def year
|
29
|
+
date.year
|
30
|
+
end
|
31
|
+
|
32
|
+
def month
|
33
|
+
date.month
|
34
|
+
end
|
35
|
+
|
36
|
+
def day
|
37
|
+
date.day
|
38
|
+
end
|
39
|
+
|
40
|
+
def to_url
|
41
|
+
date.present? ? "/#{year}/#{month}/#{day}/#{slug}/" : "/#{slug}/"
|
42
|
+
end
|
43
|
+
|
44
|
+
def disqus?
|
45
|
+
disqus && published?
|
46
|
+
end
|
47
|
+
|
48
|
+
def published?
|
49
|
+
status == 'published'
|
50
|
+
end
|
51
|
+
|
52
|
+
def post?
|
53
|
+
date.present?
|
54
|
+
end
|
55
|
+
|
56
|
+
def page?
|
57
|
+
!post?
|
58
|
+
end
|
59
|
+
|
60
|
+
class << self
|
61
|
+
def latest(options = {})
|
62
|
+
options = {published_only: false}.merge(options)
|
63
|
+
|
64
|
+
posts = documents.select(&:date)
|
65
|
+
posts = posts.select(&:published?) if options[:published_only]
|
66
|
+
posts.sort_by(&:date).reverse.first(10)
|
67
|
+
end
|
68
|
+
|
69
|
+
def with_slug(slug)
|
70
|
+
documents.detect { |p| p.slug == slug }
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Schreihals
|
2
|
+
class Static
|
3
|
+
def initialize(app, public_dir = './public')
|
4
|
+
@file = Rack::File.new(public_dir)
|
5
|
+
@app = app
|
6
|
+
end
|
7
|
+
|
8
|
+
def call(env)
|
9
|
+
status, headers, body = @file.call(env)
|
10
|
+
if status > 400
|
11
|
+
@app.call(env)
|
12
|
+
else
|
13
|
+
[status, headers, body]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/schreihals/version.rb
CHANGED
@@ -0,0 +1 @@
|
|
1
|
+
first_post
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler/setup'
|
3
|
+
require 'schreihals'
|
4
|
+
|
5
|
+
class MyBlog < Schreihals::App
|
6
|
+
set :blog_title, "<%= @name %>"
|
7
|
+
set :blog_url, "http://<%= @name %>.info"
|
8
|
+
set :blog_description, ""
|
9
|
+
set :author_name, "Your Name"
|
10
|
+
# set :disqus_name, ""
|
11
|
+
# set :google_analytics_id, ""
|
12
|
+
end
|
13
|
+
|
14
|
+
run MyBlog
|
File without changes
|
File without changes
|
data/lib/views/404.haml
CHANGED
data/lib/views/blog.scss
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
@import 'schreihals';
|
data/lib/views/index.haml
CHANGED
data/lib/views/layout.haml
CHANGED
@@ -2,19 +2,23 @@
|
|
2
2
|
%html
|
3
3
|
%head
|
4
4
|
%title= [@page_title, settings.blog_title].compact.join(" | ")
|
5
|
-
%
|
5
|
+
%meta{ name: "viewport", content: "width=device-width, initial-scale=1.0" }
|
6
|
+
%link{ href: '/blog.css', media: "screen", rel: "stylesheet", type: "text/css" }
|
6
7
|
%link{ href: '/atom.xml', title: "Subscribe via Atom Feed", rel: 'alternate', type: 'application/atom+xml' }
|
7
8
|
%body
|
8
|
-
|
9
|
-
|
9
|
+
.container
|
10
|
+
%header
|
10
11
|
%h1
|
11
12
|
= link_to settings.blog_title, '/'
|
13
|
+
- if @show_description
|
14
|
+
~ markdown settings.blog_description
|
12
15
|
|
13
|
-
|
16
|
+
= yield
|
14
17
|
|
15
|
-
|
16
|
-
|
17
|
-
~ markdown settings.blog_description
|
18
|
+
%footer
|
19
|
+
~ markdown settings.footer
|
18
20
|
|
19
|
-
|
20
|
-
|
21
|
+
- if production? && settings.google_analytics_id.present?
|
22
|
+
= partial 'google_analytics'
|
23
|
+
- if production? && settings.gauges_id.present?
|
24
|
+
= partial 'gauges'
|
@@ -0,0 +1,12 @@
|
|
1
|
+
:javascript
|
2
|
+
var _gauges = _gauges || [];
|
3
|
+
(function() {
|
4
|
+
var t = document.createElement('script');
|
5
|
+
t.type = 'text/javascript';
|
6
|
+
t.async = true;
|
7
|
+
t.id = 'gauges-tracker';
|
8
|
+
t.setAttribute('data-site-id', '#{settings.gauges_id}');
|
9
|
+
t.src = '//secure.gaug.es/track.js';
|
10
|
+
var s = document.getElementsByTagName('script')[0];
|
11
|
+
s.parentNode.insertBefore(t, s);
|
12
|
+
})();
|
@@ -4,6 +4,7 @@
|
|
4
4
|
- show_body ||= complete || !show_summary
|
5
5
|
- show_read_more ||= !complete && post.summary.present?
|
6
6
|
- show_permalink ||= post.post? && !show_read_more
|
7
|
+
- show_twitter ||= complete && post.post? && settings.twitter_id.present?
|
7
8
|
|
8
9
|
%article.post{class: post.status}
|
9
10
|
%header
|
@@ -27,5 +28,12 @@
|
|
27
28
|
- if show_body
|
28
29
|
~ post.to_html
|
29
30
|
|
30
|
-
|
31
|
-
|
31
|
+
%footer
|
32
|
+
- if show_permalink
|
33
|
+
%p.permalink= link_to '∞', post
|
34
|
+
- if show_twitter
|
35
|
+
.social_media_buttons
|
36
|
+
- if show_twitter
|
37
|
+
%a{ href: "https://twitter.com/share", class: "twitter-share-button", data: { via: settings.twitter_id } }
|
38
|
+
:javascript
|
39
|
+
!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");
|
data/lib/views/post.haml
CHANGED
@@ -1,10 +1,7 @@
|
|
1
1
|
- set_page_title @post.title.presence
|
2
2
|
|
3
|
-
|
4
|
-
.container
|
5
|
-
= partial @post, complete: true
|
3
|
+
= partial @post, complete: true
|
6
4
|
|
7
5
|
- if show_disqus? && @post.disqus?
|
8
6
|
%section.disqus
|
9
|
-
.
|
10
|
-
= partial 'disqus', :disqus_identifier => @post.disqus_identifier
|
7
|
+
= partial 'disqus', :disqus_identifier => @post.disqus_identifier
|
data/lib/views/schreihals.scss
CHANGED
@@ -1,30 +1,41 @@
|
|
1
|
-
|
1
|
+
// load stuff!
|
2
2
|
@import 'schnitzelstyle';
|
3
3
|
@import 'schnitzelstyle/coderay';
|
4
|
-
|
5
|
-
$font-default: 16px "PT Serif";
|
6
|
-
$font-headlines: 15px "Inder";
|
7
|
-
$font-footer: 11px "Inder";
|
4
|
+
@import 'schnitzelstyle/export';
|
8
5
|
|
9
6
|
@include schnitzel-complete;
|
7
|
+
@include schnitzel-export;
|
10
8
|
|
11
|
-
|
12
|
-
|
9
|
+
/* misc crap */
|
10
|
+
.social_media_buttons {
|
11
|
+
margin: 1em 0;
|
13
12
|
}
|
14
13
|
|
14
|
+
/* posts */
|
15
15
|
article.post {
|
16
|
-
margin: 5em 0;
|
17
16
|
header {
|
18
|
-
|
19
|
-
|
17
|
+
.info {
|
18
|
+
display: inline;
|
19
|
+
margin-left: 1em;
|
20
|
+
color: #999;
|
21
|
+
}
|
20
22
|
}
|
21
23
|
|
22
24
|
&.draft header h2 { background-color: #ccc; }
|
23
25
|
|
24
26
|
div.summary p {
|
25
|
-
font:
|
27
|
+
font: $font-header;
|
28
|
+
font-size: 115%;
|
26
29
|
line-height: 150%;
|
27
30
|
color: #000;
|
31
|
+
|
32
|
+
@media only screen and (max-width: 640px) {
|
33
|
+
line-height: 130%;
|
34
|
+
|
35
|
+
section.posts & {
|
36
|
+
font-size: 100%;
|
37
|
+
}
|
38
|
+
}
|
28
39
|
}
|
29
40
|
|
30
41
|
p.permalink {
|
@@ -35,6 +46,7 @@ article.post {
|
|
35
46
|
}
|
36
47
|
}
|
37
48
|
|
49
|
+
/* disqus */
|
38
50
|
#dsq-content {
|
39
51
|
a {
|
40
52
|
border: 0;
|
@@ -43,7 +55,7 @@ article.post {
|
|
43
55
|
margin-bottom: 2em;
|
44
56
|
}
|
45
57
|
h3 {
|
46
|
-
margin-top: 1em;
|
58
|
+
margin-top: 1em !important;
|
47
59
|
@include clearfix;
|
48
60
|
}
|
49
61
|
}
|
data/schreihals.gemspec
CHANGED
@@ -15,17 +15,26 @@ Gem::Specification.new do |gem|
|
|
15
15
|
gem.require_paths = ["lib"]
|
16
16
|
gem.version = Schreihals::VERSION
|
17
17
|
|
18
|
-
gem.add_dependency '
|
19
|
-
gem.add_dependency '
|
18
|
+
gem.add_dependency 'rack', '~> 1.4.0'
|
19
|
+
gem.add_dependency 'sinatra', '~> 1.3.2'
|
20
|
+
gem.add_dependency 'activesupport', '~> 3.1.0'
|
20
21
|
gem.add_dependency 'shotgun'
|
21
22
|
gem.add_dependency 'haml'
|
22
23
|
gem.add_dependency 'sass'
|
23
|
-
gem.add_dependency 'document_mapper'
|
24
24
|
gem.add_dependency 'coderay'
|
25
25
|
gem.add_dependency 'redcarpet'
|
26
26
|
gem.add_dependency 'rack-cache'
|
27
27
|
gem.add_dependency 'rack-codehighlighter'
|
28
|
-
gem.add_dependency 'schnitzelstyle', '
|
28
|
+
gem.add_dependency 'schnitzelstyle', '~> 0.0.2'
|
29
|
+
gem.add_dependency 'nokogiri'
|
30
|
+
gem.add_dependency 'thor'
|
31
|
+
gem.add_dependency 'psych'
|
32
|
+
gem.add_dependency 'i18n'
|
33
|
+
gem.add_dependency 'tilt', '~> 1.3.0'
|
29
34
|
|
30
|
-
gem.add_development_dependency '
|
35
|
+
gem.add_development_dependency 'rake'
|
36
|
+
gem.add_development_dependency 'riot'
|
37
|
+
gem.add_development_dependency 'rack-test'
|
38
|
+
gem.add_development_dependency 'watchr'
|
39
|
+
gem.add_development_dependency 'awesome_print'
|
31
40
|
end
|
data/test/app_test.rb
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
require_relative 'test_helper'
|
2
|
+
|
3
|
+
class MyTestApp < Schreihals::App
|
4
|
+
set :documents_source, './test/posts'
|
5
|
+
set :blog_title, "A Little Test Blog"
|
6
|
+
set :footer, "This is just a test blog. Have fun."
|
7
|
+
end
|
8
|
+
|
9
|
+
context Schreihals::App do
|
10
|
+
setup { Rack::MockRequest.new(MyTestApp.new) }
|
11
|
+
|
12
|
+
context "when loading the home page" do
|
13
|
+
setup { topic.get '/' }
|
14
|
+
|
15
|
+
asserts(:status).equals 200
|
16
|
+
asserts(:body).present
|
17
|
+
asserts(:content_type).equals 'text/html;charset=utf-8'
|
18
|
+
asserts(:body).includes_elements("section.posts article.post", 2)
|
19
|
+
|
20
|
+
asserts(:body).includes_html('title' => MyTestApp.settings.blog_title)
|
21
|
+
asserts(:body).includes_html('.container>footer' => MyTestApp.settings.footer)
|
22
|
+
end
|
23
|
+
|
24
|
+
context "when loading a specific post's page" do
|
25
|
+
setup { topic.get '/2011/12/23/first-post/' }
|
26
|
+
|
27
|
+
asserts(:status).equals 200
|
28
|
+
asserts(:body).present
|
29
|
+
asserts(:content_type).equals 'text/html;charset=utf-8'
|
30
|
+
asserts(:body).includes_elements("article.post", 1)
|
31
|
+
asserts(:body).includes_html('article.post header h2 a' => "First Post\.")
|
32
|
+
end
|
33
|
+
|
34
|
+
context "when loading a static page" do
|
35
|
+
setup { topic.get '/static-page/' }
|
36
|
+
|
37
|
+
asserts(:status).equals 200
|
38
|
+
asserts(:body).present
|
39
|
+
asserts(:content_type).equals 'text/html;charset=utf-8'
|
40
|
+
asserts(:body).includes_elements("article.post", 1)
|
41
|
+
asserts(:body).includes_html('article.post header h2 a' => "A Static Page\.")
|
42
|
+
end
|
43
|
+
|
44
|
+
context "when loading the ATOM feed" do
|
45
|
+
setup { topic.get '/atom.xml' }
|
46
|
+
|
47
|
+
asserts(:status).equals 200
|
48
|
+
asserts(:body).present
|
49
|
+
asserts(:content_type).equals 'application/xml+atom'
|
50
|
+
asserts(:body).includes_elements("entry", 2)
|
51
|
+
end
|
52
|
+
|
53
|
+
context "when loading a static asset provided by schreihals" do
|
54
|
+
setup { topic.get '/favicon.ico' }
|
55
|
+
|
56
|
+
asserts(:status).equals 200
|
57
|
+
asserts(:body).present
|
58
|
+
asserts(:content_type).equals 'image/vnd.microsoft.icon'
|
59
|
+
end
|
60
|
+
|
61
|
+
context "when loading an invalid URL" do
|
62
|
+
setup { topic.get '/ooga/booga/foo/to/the/bar' }
|
63
|
+
|
64
|
+
asserts(:status).equals 404
|
65
|
+
asserts(:body).present
|
66
|
+
asserts(:content_type).equals 'text/html;charset=utf-8'
|
67
|
+
end
|
68
|
+
end
|