Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

initial commit

  • Loading branch information...
commit 3cf734c07310516d2e6c49f3992ac35802114380 0 parents
@auxbuss authored
1  .gitignore
@@ -0,0 +1 @@
+/nbproject/*
3  LICENSE
@@ -0,0 +1,3 @@
+== sinatra_git_blog
+
+Put appropriate LICENSE for your project here.
3  README
@@ -0,0 +1,3 @@
+== sinatra_git_blog
+
+You should document your project here.
51 Rakefile
@@ -0,0 +1,51 @@
+#
+# To change this template, choose Tools | Templates
+# and open the template in the editor.
+
+
+require 'rubygems'
+require 'rake'
+require 'rake/clean'
+require 'rake/gempackagetask'
+require 'rake/rdoctask'
+require 'rake/testtask'
+require 'spec/rake/spectask'
+
+spec = Gem::Specification.new do |s|
+ s.name = 'sinatra_git_blog'
+ s.version = '0.0.1'
+ s.has_rdoc = true
+ s.extra_rdoc_files = ['README', 'LICENSE']
+ s.summary = 'Your summary here'
+ s.description = s.summary
+ s.author = ''
+ s.email = ''
+ # s.executables = ['your_executable_here']
+ s.files = %w(LICENSE README Rakefile) + Dir.glob("{bin,lib,spec}/**/*")
+ s.require_path = "lib"
+ s.bindir = "bin"
+end
+
+Rake::GemPackageTask.new(spec) do |p|
+ p.gem_spec = spec
+ p.need_tar = true
+ p.need_zip = true
+end
+
+Rake::RDocTask.new do |rdoc|
+ files =['README', 'LICENSE', 'lib/**/*.rb']
+ rdoc.rdoc_files.add(files)
+ rdoc.main = "README" # page to start on
+ rdoc.title = "sinatra_git_blog Docs"
+ rdoc.rdoc_dir = 'doc/rdoc' # rdoc output folder
+ rdoc.options << '--line-numbers'
+end
+
+Rake::TestTask.new do |t|
+ t.test_files = FileList['test/**/*.rb']
+end
+
+Spec::Rake::SpecTask.new do |t|
+ t.spec_files = FileList['spec/**/*.rb']
+ t.libs << Dir["lib"]
+end
7 config.ru
@@ -0,0 +1,7 @@
+$LOAD_PATH.unshift 'lib'
+
+require 'rack/cache'
+use Rack::Cache
+
+require 'main'
+run Blog
32 lib/github_hook.rb
@@ -0,0 +1,32 @@
+require 'sinatra/base'
+require 'time'
+
+class GithubHook < Sinatra::Base
+ def self.parse_git
+ sha1, date = `git log HEAD~1..HEAD --pretty=format:%h^%ci`.strip.split('^')
+ set :commit_hash, sha1
+ set :commit_date, Time.parse(date)
+ end
+
+ set(:autopull) { production? }
+ parse_git
+
+ before do
+ cache_control :public, :must_revalidate
+ etag settings.commit_hash
+ last_modified settings.commit_date
+ end
+
+ post '/update' do
+ settings.parse_git
+ app.settings.reset!
+ load app.settings.app_file
+ content_type :txt
+ if settings.autopull?
+ `git pull 2>&1`
+ else
+ "ok"
+ end
+ end
+
+end
27 lib/main.rb
@@ -0,0 +1,27 @@
+require 'sinatra/base'
+require 'github_hook'
+require 'ostruct'
+require 'time'
+
+class Blog < Sinatra::Base
+ use GithubHook
+ set :root, File.expand_path('../../', __FILE__)
+ set :articles, []
+ set :app_file, __FILE__
+ Dir.glob "#{root}/articles/*.md" do |file|
+ meta, content = File.read(file).split("\n\n", 2)
+ article = OpenStruct.new YAML.load(meta)
+ article.date = Time.parse article.date.to_s
+ article.content = content
+ article.slug = File.basename(file, '.md')
+ get "/#{article.slug}" do
+ erb :post, :locals => { :article => article }
+ end
+ articles << article
+ end
+ articles.sort_by! { |article| article.date }
+ articles.reverse!
+ get '/' do
+ erb :index
+ end
+end
24 public/css/blog.css
@@ -0,0 +1,24 @@
+body {
+ font-family: "Helvetica Neue", Arial, Helvetica, sans-serif;
+}
+article {
+ min-width: 300px;
+ max-width: 700px;
+ margin: 50px auto;
+ padding: 0 50px;
+}
+header h1 {
+ margin: 0;
+}
+header a {
+ color: #000;
+ text-decoration: none;
+ text-shadow: 1px 1px 2px #555;
+}
+header a:hover {
+ text-decoration: underline;
+}
+header time {
+ font-size: 80%;
+ color: #555;
+}
3  public/js/blog.js
@@ -0,0 +1,3 @@
+$(document).ready(function() {
+ $("time.timeago").timeago();
+});
146 public/js/jquery.timeago.js
@@ -0,0 +1,146 @@
+/**
+ * Timeago is a jQuery plugin that makes it easy to support automatically
+ * updating fuzzy timestamps (e.g. "4 minutes ago" or "about 1 day ago").
+ *
+ * @name timeago
+ * @version 0.10.0
+ * @requires jQuery v1.2.3+
+ * @author Ryan McGeary
+ * @license MIT License - http://www.opensource.org/licenses/mit-license.php
+ *
+ * For usage and examples, visit:
+ * http://timeago.yarp.com/
+ *
+ * Copyright (c) 2008-2011, Ryan McGeary (ryanonjavascript -[at]- mcgeary [*dot*] org)
+ */
+(function($) {
+ $.timeago = function(timestamp) {
+ if (timestamp instanceof Date) {
+ return inWords(timestamp);
+ } else if (typeof timestamp === "string") {
+ return inWords($.timeago.parse(timestamp));
+ } else {
+ return inWords($.timeago.datetime(timestamp));
+ }
+ };
+ var $t = $.timeago;
+
+ $.extend($.timeago, {
+ settings: {
+ refreshMillis: 60000,
+ allowFuture: false,
+ strings: {
+ prefixAgo: null,
+ prefixFromNow: null,
+ suffixAgo: "ago",
+ suffixFromNow: "from now",
+ seconds: "less than a minute",
+ minute: "about a minute",
+ minutes: "%d minutes",
+ hour: "about an hour",
+ hours: "about %d hours",
+ day: "a day",
+ days: "%d days",
+ month: "about a month",
+ months: "%d months",
+ year: "about a year",
+ years: "%d years",
+ numbers: []
+ }
+ },
+ inWords: function(distanceMillis) {
+ var $l = this.settings.strings;
+ var prefix = $l.prefixAgo;
+ var suffix = $l.suffixAgo;
+ if (this.settings.allowFuture) {
+ if (distanceMillis < 0) {
+ prefix = $l.prefixFromNow;
+ suffix = $l.suffixFromNow;
+ }
+ }
+
+ var seconds = Math.abs(distanceMillis) / 1000;
+ var minutes = seconds / 60;
+ var hours = minutes / 60;
+ var days = hours / 24;
+ var years = days / 365;
+
+ function substitute(stringOrFunction, number) {
+ var string = $.isFunction(stringOrFunction) ? stringOrFunction(number, distanceMillis) : stringOrFunction;
+ var value = ($l.numbers && $l.numbers[number]) || number;
+ return string.replace(/%d/i, value);
+ }
+
+ var words = seconds < 45 && substitute($l.seconds, Math.round(seconds)) ||
+ seconds < 90 && substitute($l.minute, 1) ||
+ minutes < 45 && substitute($l.minutes, Math.round(minutes)) ||
+ minutes < 90 && substitute($l.hour, 1) ||
+ hours < 24 && substitute($l.hours, Math.round(hours)) ||
+ hours < 48 && substitute($l.day, 1) ||
+ days < 30 && substitute($l.days, Math.floor(days)) ||
+ days < 60 && substitute($l.month, 1) ||
+ days < 365 && substitute($l.months, Math.floor(days / 30)) ||
+ years < 2 && substitute($l.year, 1) ||
+ substitute($l.years, Math.floor(years));
+
+ return $.trim([prefix, words, suffix].join(" "));
+ },
+ parse: function(iso8601) {
+ var s = $.trim(iso8601);
+ s = s.replace(/\.\d\d\d+/,""); // remove milliseconds
+ s = s.replace(/-/,"/").replace(/-/,"/");
+ s = s.replace(/T/," ").replace(/Z/," UTC");
+ s = s.replace(/([\+\-]\d\d)\:?(\d\d)/," $1$2"); // -04:00 -> -0400
+ return new Date(s);
+ },
+ datetime: function(elem) {
+ // jQuery's `is()` doesn't play well with HTML5 in IE
+ var isTime = $(elem).get(0).tagName.toLowerCase() === "time"; // $(elem).is("time");
+ var iso8601 = isTime ? $(elem).attr("datetime") : $(elem).attr("title");
+ return $t.parse(iso8601);
+ }
+ });
+
+ $.fn.timeago = function() {
+ var self = this;
+ self.each(refresh);
+
+ var $s = $t.settings;
+ if ($s.refreshMillis > 0) {
+ setInterval(function() { self.each(refresh); }, $s.refreshMillis);
+ }
+ return self;
+ };
+
+ function refresh() {
+ var data = prepareData(this);
+ if (!isNaN(data.datetime)) {
+ $(this).text(inWords(data.datetime));
+ }
+ return this;
+ }
+
+ function prepareData(element) {
+ element = $(element);
+ if (!element.data("timeago")) {
+ element.data("timeago", { datetime: $t.datetime(element) });
+ var text = $.trim(element.text());
+ if (text.length > 0) {
+ element.attr("title", text);
+ }
+ }
+ return element.data("timeago");
+ }
+
+ function inWords(date) {
+ return $t.inWords(distance(date));
+ }
+
+ function distance(date) {
+ return (new Date().getTime() - date.getTime());
+ }
+
+ // fix for IE6 suckage
+ document.createElement("abbr");
+ document.createElement("time");
+}(jQuery));
3  views/index.erb
@@ -0,0 +1,3 @@
+<% settings.articles.each do |article| %>
+ <%= erb :post, :locals => { :article => article } %>
+<% end %>
13 views/layout.erb
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>My Blog</title>
+ <link rel="stylesheet" media="screen" href="/css/blog.css" />
+ <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
+ <script type="text/javascript" src="/js/jquery.timeago.js"></script>
+ <script type="text/javascript" src="/js/blog.js"></script>
+ </head>
+ <body>
+ <%= yield %>
+ </body>
+</html>
13 views/post.erb
@@ -0,0 +1,13 @@
+<article>
+ <header>
+ <h1>
+ <a href="<%= url(article.slug) %>"><%= article.title %></a>
+ </h1>
+ <time class="timeago" datetime="<%= article.date.xmlschema %>">
+ <%= article.date.strftime "%Y/%m/%d" %>
+ </time>
+ </header>
+ <section class="content">
+ <%= markdown article.content %>
+ </section>
+</article>
Please sign in to comment.
Something went wrong with that request. Please try again.