schreihals 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Schreihals
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -0,0 +1 @@
1
+ first_post
@@ -0,0 +1,13 @@
1
+ ---
2
+ title: <%= @title %>
3
+ summary:
4
+ link:
5
+
6
+ # More options:
7
+ #
8
+ # status: draft
9
+ # read_more:
10
+ # disqus: false
11
+ ---
12
+
13
+ <%= @text %>
@@ -0,0 +1,5 @@
1
+ .bundle
2
+ .rbfu-version
3
+ .powenv
4
+ .sass-cache
5
+ tmp
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'schreihals', '~> 0.0.2'
@@ -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
@@ -1,5 +1,4 @@
1
1
  %section
2
- .container
3
- %h2 400 + 4
4
- %p
5
- The document you requested could not be found.
2
+ %h2 400 + 4
3
+ %p
4
+ The document you requested could not be found.
@@ -0,0 +1 @@
1
+ @import 'schreihals';
@@ -1,4 +1,3 @@
1
1
  %section.posts
2
- .container
3
- - @posts.each do |post|
4
- = partial post
2
+ - @posts.each do |post|
3
+ = partial post
@@ -2,19 +2,23 @@
2
2
  %html
3
3
  %head
4
4
  %title= [@page_title, settings.blog_title].compact.join(" | ")
5
- %link{href: '/schreihals.css', media: "screen", rel: "stylesheet", type: "text/css"}
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
- %header
9
- .container
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
- = yield
16
+ = yield
14
17
 
15
- %footer
16
- .container
17
- ~ markdown settings.blog_description
18
+ %footer
19
+ ~ markdown settings.footer
18
20
 
19
- - if production? && settings.google_analytics_id.present?
20
- = partial 'google_analytics'
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
- - if show_permalink
31
- %p.permalink= link_to '∞', post
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");
@@ -1,10 +1,7 @@
1
1
  - set_page_title @post.title.presence
2
2
 
3
- %section.post
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
- .container
10
- = partial 'disqus', :disqus_identifier => @post.disqus_identifier
7
+ = partial 'disqus', :disqus_identifier => @post.disqus_identifier
@@ -1,30 +1,41 @@
1
- @import url(http://fonts.googleapis.com/css?family=Inder|PT+Serif);
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
- section.disqus {
12
- background-color: #eee !important;
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
- margin-bottom: 1em;
19
- .info { display: inline; margin-left: 1em; color: #999 }
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: 18px "Inder";
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
  }
@@ -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 'sinatra'
19
- gem.add_dependency 'activesupport'
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', '>= 0.0.1'
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 'rspec', '>= 2.0.0'
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
@@ -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