allegro 0.0.0pre
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/README.md +15 -0
- data/bin/allegro +13 -0
- data/lib/allegro.rb +53 -0
- data/lib/allegro/archives.rb +21 -0
- data/lib/allegro/article.rb +103 -0
- data/lib/allegro/context.rb +45 -0
- data/lib/allegro/ext/ext.rb +46 -0
- data/lib/allegro/repo.rb +21 -0
- data/lib/allegro/server.rb +42 -0
- data/lib/allegro/site.rb +94 -0
- data/lib/allegro/template.rb +30 -0
- data/lib/allegro/version.rb +3 -0
- data/lib/template/README +4 -0
- data/lib/template/Rakefile +42 -0
- data/lib/template/articles/1900-05-17-the-wonderful-wizard-of-oz.txt +7 -0
- data/lib/template/config.ru +35 -0
- data/lib/template/public/css/main.css +110 -0
- data/lib/template/templates/index.builder +21 -0
- data/lib/template/templates/layout.rhtml +18 -0
- data/lib/template/templates/pages/about.rhtml +0 -0
- data/lib/template/templates/pages/archives.rhtml +11 -0
- data/lib/template/templates/pages/article.rhtml +20 -0
- data/lib/template/templates/pages/index.rhtml +20 -0
- metadata +88 -0
data/README.md
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
Allegro
|
2
|
+
=======
|
3
|
+
(tryin' to improve cloudhead's toto)
|
4
|
+
-------------------------------------
|
5
|
+
0. Install the gem.
|
6
|
+
1. run:
|
7
|
+
allegro new myblog
|
8
|
+
2. enjoy
|
9
|
+
|
10
|
+
|
11
|
+
-------------------------------------
|
12
|
+
_...of this astounding life down here_
|
13
|
+
_and of the strange clowns in control of it_
|
14
|
+
|
15
|
+
_**Lawrence Ferlinghetti**_
|
data/bin/allegro
ADDED
data/lib/allegro.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
$:.unshift File.dirname(__FILE__)
|
2
|
+
LIBDIR = File.dirname(__FILE__)
|
3
|
+
|
4
|
+
require 'yaml'
|
5
|
+
require 'date'
|
6
|
+
require 'erb'
|
7
|
+
require 'rack'
|
8
|
+
require 'digest'
|
9
|
+
require 'open-uri'
|
10
|
+
require 'rdiscount'
|
11
|
+
require 'builder'
|
12
|
+
require 'fileutils'
|
13
|
+
|
14
|
+
require 'allegro/ext/ext'
|
15
|
+
require 'allegro/version'
|
16
|
+
require 'allegro/template'
|
17
|
+
require 'allegro/site'
|
18
|
+
require 'allegro/repo'
|
19
|
+
require 'allegro/context'
|
20
|
+
require 'allegro/archives'
|
21
|
+
require 'allegro/article'
|
22
|
+
require 'allegro/server'
|
23
|
+
|
24
|
+
module Allegro
|
25
|
+
Paths = {
|
26
|
+
:templates => "templates",
|
27
|
+
:pages => "templates/pages",
|
28
|
+
:articles => "articles"
|
29
|
+
}
|
30
|
+
|
31
|
+
def self.env
|
32
|
+
ENV['RACK_ENV'] || 'production'
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.env= env
|
36
|
+
ENV['RACK_ENV'] = env
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.stub(blog)
|
40
|
+
puts "\nAllegro is...\n - \033[32mCreating\033[0m your blog '#{blog}'"
|
41
|
+
Dir.mkdir blog
|
42
|
+
|
43
|
+
puts " - \033[32mCopying\033[0m blog template"
|
44
|
+
FileUtils.cp_r( Dir.glob(File.join(LIBDIR, 'template/*')), blog )
|
45
|
+
|
46
|
+
puts "\n \033[32mCongratulations, '#{blog}' is ready to go!\033[0m"
|
47
|
+
rescue Errno::EEXIST
|
48
|
+
puts "\n \033[31muh oh, directory '#{blog}' already exists...\033[0m"
|
49
|
+
exit
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Allegro
|
2
|
+
class Archives < Array
|
3
|
+
include Template
|
4
|
+
|
5
|
+
def initialize articles, config
|
6
|
+
self.replace articles
|
7
|
+
@config = config
|
8
|
+
end
|
9
|
+
|
10
|
+
def [] a
|
11
|
+
a.is_a?(Range) ? self.class.new(self.slice(a) || [], @config) : super
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_html
|
15
|
+
super(:archives, @config)
|
16
|
+
end
|
17
|
+
alias :to_s to_html
|
18
|
+
alias :archive archives
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
@@ -0,0 +1,103 @@
|
|
1
|
+
module Allegro
|
2
|
+
|
3
|
+
class Article < Hash
|
4
|
+
include Template
|
5
|
+
|
6
|
+
def initialize obj, config = {}
|
7
|
+
@obj, @config = obj, config
|
8
|
+
self.load if obj.is_a? Hash
|
9
|
+
end
|
10
|
+
|
11
|
+
def load
|
12
|
+
data = if @obj.is_a? String
|
13
|
+
meta, self[:body] = File.read(@obj).split(/\n\n/, 2)
|
14
|
+
|
15
|
+
# use the date from the filename, or else allegro won't find the article
|
16
|
+
@obj =~ /\/(\d{4}-\d{2}-\d{2})[^\/]*$/
|
17
|
+
($1 ? {:date => $1} : {}).merge(YAML.load(meta))
|
18
|
+
elsif @obj.is_a? Hash
|
19
|
+
@obj
|
20
|
+
end.inject({}) {|h, (k,v)| h.merge(k.to_sym => v) }
|
21
|
+
|
22
|
+
self.taint
|
23
|
+
self.update data
|
24
|
+
self[:date] = Date.parse(self[:date].gsub('/', '-')) rescue Date.today
|
25
|
+
self
|
26
|
+
end
|
27
|
+
|
28
|
+
def [] key
|
29
|
+
self.load unless self.tainted?
|
30
|
+
super
|
31
|
+
end
|
32
|
+
|
33
|
+
def slug
|
34
|
+
self[:slug] || self[:title].slugize
|
35
|
+
end
|
36
|
+
|
37
|
+
def summary length = nil
|
38
|
+
config = @config[:summary]
|
39
|
+
sum = if self[:body] =~ config[:delim]
|
40
|
+
self[:body].split(config[:delim]).first
|
41
|
+
else
|
42
|
+
self[:body].match(/(.{1,#{length || config[:length] || config[:max]}}.*?)(\n|\Z)/m).to_s
|
43
|
+
end
|
44
|
+
markdown(sum.length == self[:body].length ? sum : sum.strip.sub(/\.\Z/, '…'))
|
45
|
+
end
|
46
|
+
|
47
|
+
def url
|
48
|
+
"http://#{(@config[:url].sub("http://", '') + self.path).squeeze('/')}"
|
49
|
+
end
|
50
|
+
alias :permalink url
|
51
|
+
|
52
|
+
def body
|
53
|
+
markdown self[:body].sub(@config[:summary][:delim], '') rescue markdown self[:body]
|
54
|
+
end
|
55
|
+
|
56
|
+
def path
|
57
|
+
"/#{@config[:prefix]}#{self[:date].strftime("/%Y/%m/%d/#{slug}/")}".squeeze('/')
|
58
|
+
end
|
59
|
+
|
60
|
+
def title() self[:title] || "an article" end
|
61
|
+
def date() @config[:date].call(self[:date]) end
|
62
|
+
def author() self[:author] || @config[:author] end
|
63
|
+
def to_html() self.load; super(:article, @config) end
|
64
|
+
alias :to_s to_html
|
65
|
+
end
|
66
|
+
|
67
|
+
class Config < Hash
|
68
|
+
Defaults = {
|
69
|
+
:author => ENV['USER'], # blog author
|
70
|
+
:title => Dir.pwd.split('/').last, # site title
|
71
|
+
:root => "index", # site index
|
72
|
+
:url => "http://127.0.0.1", # root URL of the site
|
73
|
+
:prefix => "", # common path prefix for the blog
|
74
|
+
:date => lambda {|now| now.strftime("%d/%m/%Y") }, # date function
|
75
|
+
:markdown => :smart, # use markdown
|
76
|
+
:disqus => false, # disqus name
|
77
|
+
:summary => {:max => 150, :delim => /~\n/}, # length of summary and delimiter
|
78
|
+
:ext => 'txt', # extension for articles
|
79
|
+
:cache => 28800, # cache duration (seconds)
|
80
|
+
:github => {:user => "", :repos => [], :ext => 'md'}, # Github username and list of repos
|
81
|
+
:to_html => lambda {|path, page, ctx| # returns an html, from a path & context
|
82
|
+
ERB.new(File.read("#{path}/#{page}.rhtml")).result(ctx)
|
83
|
+
},
|
84
|
+
:error => lambda {|code| # The HTML for your error page
|
85
|
+
"<font style='font-size:300%'>allegro, we're not in Kansas anymore (#{code})</font>"
|
86
|
+
}
|
87
|
+
}
|
88
|
+
def initialize obj
|
89
|
+
self.update Defaults
|
90
|
+
self.update obj
|
91
|
+
end
|
92
|
+
|
93
|
+
def set key, val = nil, &blk
|
94
|
+
if val.is_a? Hash
|
95
|
+
self[key].update val
|
96
|
+
else
|
97
|
+
self[key] = block_given?? blk : val
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Allegro
|
2
|
+
|
3
|
+
class Site
|
4
|
+
|
5
|
+
class Context
|
6
|
+
include Template
|
7
|
+
attr_reader :env
|
8
|
+
|
9
|
+
def initialize ctx = {}, config = {}, path = "/", env = {}
|
10
|
+
@config, @context, @path, @env = config, ctx, path, env
|
11
|
+
@articles = Site.articles(@config[:ext]).reverse.map do |a|
|
12
|
+
Article.new(a, @config)
|
13
|
+
end
|
14
|
+
|
15
|
+
ctx.each do |k, v|
|
16
|
+
meta_def(k) { ctx.instance_of?(Hash) ? v : ctx.send(k) }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def title
|
21
|
+
@config[:title]
|
22
|
+
end
|
23
|
+
|
24
|
+
def render page, type
|
25
|
+
if type == :html
|
26
|
+
content = to_html page, @config
|
27
|
+
to_html(:layout, @config, &Proc.new { content })
|
28
|
+
else
|
29
|
+
send(:"to_#{type}", page)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def to_xml page
|
34
|
+
xml = Builder::XmlMarkup.new(:indent => 2)
|
35
|
+
instance_eval File.read("#{Paths[:templates]}/#{page}.builder")
|
36
|
+
end
|
37
|
+
alias :to_atom to_xml
|
38
|
+
|
39
|
+
def method_missing m, *args, &blk
|
40
|
+
@context.respond_to?(m) ? @context.send(m, *args, &blk) : super
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
@@ -0,0 +1,46 @@
|
|
1
|
+
class Object
|
2
|
+
def meta_def name, &blk
|
3
|
+
(class << self; self; end).instance_eval do
|
4
|
+
define_method(name, &blk)
|
5
|
+
end
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class String
|
10
|
+
def slugize
|
11
|
+
self.downcase.gsub(/&/, 'and').gsub(/\s+/, '-').gsub(/[^a-z0-9-]/, '')
|
12
|
+
end
|
13
|
+
|
14
|
+
def humanize
|
15
|
+
self.capitalize.gsub(/[-_]+/, ' ')
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class Fixnum
|
20
|
+
def ordinal
|
21
|
+
# 1 => 1st
|
22
|
+
# 2 => 2nd
|
23
|
+
# 3 => 3rd
|
24
|
+
# ...
|
25
|
+
case self % 100
|
26
|
+
when 11..13; "#{self}th"
|
27
|
+
else
|
28
|
+
case self % 10
|
29
|
+
when 1; "#{self}st"
|
30
|
+
when 2; "#{self}nd"
|
31
|
+
when 3; "#{self}rd"
|
32
|
+
else "#{self}th"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class Date
|
39
|
+
# This check is for people running Toto with ActiveSupport, avoid a collision
|
40
|
+
unless respond_to? :iso8601
|
41
|
+
# Return the date as a String formatted according to ISO 8601.
|
42
|
+
def iso8601
|
43
|
+
::Time.utc(year, month, day, 0, 0, 0, 0).iso8601
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/lib/allegro/repo.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
module Allegro
|
2
|
+
|
3
|
+
class Repo < Hash
|
4
|
+
include Template
|
5
|
+
|
6
|
+
README = "http://github.com/%s/%s/raw/master/README.%s"
|
7
|
+
|
8
|
+
def initialize name, config
|
9
|
+
self[:name], @config = name, config
|
10
|
+
end
|
11
|
+
|
12
|
+
def readme
|
13
|
+
markdown open(README %
|
14
|
+
[@config[:github][:user], self[:name], @config[:github][:ext]]).read
|
15
|
+
rescue Timeout::Error, OpenURI::HTTPError => e
|
16
|
+
"This page isn't available."
|
17
|
+
end
|
18
|
+
alias :content readme
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Allegro
|
2
|
+
|
3
|
+
class Server
|
4
|
+
attr_reader :config, :site
|
5
|
+
|
6
|
+
def initialize config = {}, &blk
|
7
|
+
@config = config.is_a?(Config) ? config : Config.new(config)
|
8
|
+
@config.instance_eval(&blk) if block_given?
|
9
|
+
@site = Allegro::Site.new(@config)
|
10
|
+
end
|
11
|
+
|
12
|
+
def call env
|
13
|
+
@request = Rack::Request.new env
|
14
|
+
@response = Rack::Response.new
|
15
|
+
|
16
|
+
return [400, {}, []] unless @request.get?
|
17
|
+
|
18
|
+
path, mime = @request.path_info.split('.')
|
19
|
+
route = (path || '/').split('/').reject {|i| i.empty? }
|
20
|
+
|
21
|
+
response = @site.go(route, *(mime ? mime : []), env)
|
22
|
+
|
23
|
+
@response.body = [response[:body]]
|
24
|
+
@response['Content-Length'] = response[:body].length.to_s unless response[:body].empty?
|
25
|
+
@response['Content-Type'] = Rack::Mime.mime_type(".#{response[:type]}")
|
26
|
+
|
27
|
+
# Set http cache headers
|
28
|
+
@response['Cache-Control'] = if Allegro.env == 'production'
|
29
|
+
"public, max-age=#{@config[:cache]}"
|
30
|
+
else
|
31
|
+
"no-cache, must-revalidate"
|
32
|
+
end
|
33
|
+
|
34
|
+
@response['ETag'] = %("#{Digest::SHA1.hexdigest(response[:body])}")
|
35
|
+
|
36
|
+
@response.status = response[:status]
|
37
|
+
@response.finish
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
data/lib/allegro/site.rb
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
module Allegro
|
2
|
+
|
3
|
+
class Site
|
4
|
+
def initialize config
|
5
|
+
@config = config
|
6
|
+
end
|
7
|
+
|
8
|
+
def [] *args
|
9
|
+
@config[*args]
|
10
|
+
end
|
11
|
+
|
12
|
+
def []= key, value
|
13
|
+
@config.set key, value
|
14
|
+
end
|
15
|
+
|
16
|
+
def index type = :html
|
17
|
+
articles = type == :html ? self.articles.reverse : self.articles
|
18
|
+
{:articles => articles.map do |article|
|
19
|
+
Article.new article, @config
|
20
|
+
end}.merge archives
|
21
|
+
end
|
22
|
+
|
23
|
+
def archives filter = ""
|
24
|
+
entries = ! self.articles.empty??
|
25
|
+
self.articles.select do |a|
|
26
|
+
filter !~ /^\d{4}/ || File.basename(a) =~ /^#{filter}/
|
27
|
+
end.reverse.map do |article|
|
28
|
+
Article.new article, @config
|
29
|
+
end : []
|
30
|
+
|
31
|
+
return :archives => Archives.new(entries, @config)
|
32
|
+
end
|
33
|
+
|
34
|
+
def article route
|
35
|
+
Article.new("#{Paths[:articles]}/#{route.join('-')}.#{self[:ext]}", @config).load
|
36
|
+
end
|
37
|
+
|
38
|
+
def /
|
39
|
+
self[:root]
|
40
|
+
end
|
41
|
+
|
42
|
+
def go route, type = :html, env
|
43
|
+
route << self./ if route.empty?
|
44
|
+
type, path = type =~ /html|xml|json/ ? type.to_sym : :html, route.join('/')
|
45
|
+
context = lambda do |data, page|
|
46
|
+
Context.new(data, @config, path, env).render(page, type)
|
47
|
+
end
|
48
|
+
|
49
|
+
body, status = if Context.new.respond_to?(:"to_#{type}")
|
50
|
+
if route.first =~ /\d{4}/
|
51
|
+
case route.size
|
52
|
+
when 1..3
|
53
|
+
context[archives(route * '-'), :archives]
|
54
|
+
when 4
|
55
|
+
context[article(route), :article]
|
56
|
+
else http 400
|
57
|
+
end
|
58
|
+
elsif respond_to?(path)
|
59
|
+
context[send(path, type), path.to_sym]
|
60
|
+
elsif (repo = @config[:github][:repos].grep(/#{path}/).first) &&
|
61
|
+
!@config[:github][:user].empty?
|
62
|
+
context[Repo.new(repo, @config), :repo]
|
63
|
+
else
|
64
|
+
context[{}, path.to_sym]
|
65
|
+
end
|
66
|
+
else
|
67
|
+
http 400
|
68
|
+
end
|
69
|
+
|
70
|
+
rescue Errno::ENOENT => e
|
71
|
+
return :body => http(404).first, :type => :html, :status => 404
|
72
|
+
else
|
73
|
+
return :body => body || "", :type => type, :status => status || 200
|
74
|
+
end
|
75
|
+
|
76
|
+
protected
|
77
|
+
|
78
|
+
def http code
|
79
|
+
[@config[:error].call(code), code]
|
80
|
+
end
|
81
|
+
|
82
|
+
def articles
|
83
|
+
self.class.articles self[:ext]
|
84
|
+
end
|
85
|
+
|
86
|
+
def self.articles ext
|
87
|
+
Dir["#{Paths[:articles]}/*.#{ext}"].sort_by {|entry| File.basename(entry) }
|
88
|
+
end
|
89
|
+
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Allegro
|
2
|
+
|
3
|
+
module Template
|
4
|
+
def to_html page, config, &blk
|
5
|
+
path = ([:layout, :repo].include?(page) ? Paths[:templates] : Paths[:pages])
|
6
|
+
config[:to_html].call(path, page, binding)
|
7
|
+
end
|
8
|
+
|
9
|
+
def markdown text
|
10
|
+
if (options = @config[:markdown])
|
11
|
+
Markdown.new(text.to_s.strip, *(options.eql?(true) ? [] : options)).to_html
|
12
|
+
else
|
13
|
+
text.strip
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def method_missing m, *args, &blk
|
18
|
+
self.keys.include?(m) ? self[m] : super
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.included obj
|
22
|
+
obj.class_eval do
|
23
|
+
define_method(obj.to_s.split('::').last.downcase) { self }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
end
|
30
|
+
|
data/lib/template/README
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'toto'
|
2
|
+
|
3
|
+
@config = Toto::Config::Defaults
|
4
|
+
|
5
|
+
task :default => :new
|
6
|
+
|
7
|
+
desc "Create a new article."
|
8
|
+
task :new do
|
9
|
+
title = ask('Title: ')
|
10
|
+
slug = title.empty?? nil : title.strip.slugize
|
11
|
+
|
12
|
+
article = {'title' => title, 'date' => Time.now.strftime("%d/%m/%Y")}.to_yaml
|
13
|
+
article << "\n"
|
14
|
+
article << "Once upon a time...\n\n"
|
15
|
+
|
16
|
+
path = "#{Toto::Paths[:articles]}/#{Time.now.strftime("%Y-%m-%d")}#{'-' + slug if slug}.#{@config[:ext]}"
|
17
|
+
|
18
|
+
unless File.exist? path
|
19
|
+
File.open(path, "w") do |file|
|
20
|
+
file.write article
|
21
|
+
end
|
22
|
+
toto "an article was created for you at #{path}."
|
23
|
+
else
|
24
|
+
toto "I can't create the article, #{path} already exists."
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
desc "Publish my blog."
|
29
|
+
task :publish do
|
30
|
+
toto "publishing your article(s)..."
|
31
|
+
`git push heroku master`
|
32
|
+
end
|
33
|
+
|
34
|
+
def toto msg
|
35
|
+
puts "\n toto ~ #{msg}\n\n"
|
36
|
+
end
|
37
|
+
|
38
|
+
def ask message
|
39
|
+
print message
|
40
|
+
STDIN.gets.chomp
|
41
|
+
end
|
42
|
+
|
@@ -0,0 +1,35 @@
|
|
1
|
+
|
2
|
+
require 'allegro'
|
3
|
+
|
4
|
+
# Rack config
|
5
|
+
use Rack::Static, :urls => ['/css', '/js', '/images', '/favicon.ico'], :root => 'public'
|
6
|
+
use Rack::CommonLogger
|
7
|
+
|
8
|
+
if ENV['RACK_ENV'] == 'development'
|
9
|
+
use Rack::ShowExceptions
|
10
|
+
end
|
11
|
+
|
12
|
+
#
|
13
|
+
# Create and configure a toto instance
|
14
|
+
#
|
15
|
+
allegro = Allegro::Server.new do
|
16
|
+
#
|
17
|
+
# Add your settings here
|
18
|
+
# set [:setting], [value]
|
19
|
+
#
|
20
|
+
# set :author, ENV['USER'] # blog author
|
21
|
+
# set :title, Dir.pwd.split('/').last # site title
|
22
|
+
# set :root, "index" # page to load on /
|
23
|
+
# set :date, lambda {|now| now.strftime("%d/%m/%Y") } # date format for articles
|
24
|
+
# set :markdown, :smart # use markdown + smart-mode
|
25
|
+
# set :disqus, false # disqus id, or false
|
26
|
+
# set :summary, :max => 150, :delim => /~/ # length of article summary and delimiter
|
27
|
+
# set :ext, 'txt' # file extension for articles
|
28
|
+
# set :cache, 28800 # cache duration, in seconds
|
29
|
+
|
30
|
+
set :date, lambda {|now| now.strftime("%B #{now.day.ordinal} %Y") }
|
31
|
+
end
|
32
|
+
|
33
|
+
run allegro
|
34
|
+
|
35
|
+
|
@@ -0,0 +1,110 @@
|
|
1
|
+
html { margin: 20px }
|
2
|
+
body {
|
3
|
+
margin: 0 auto;
|
4
|
+
font-family: 'Baskerville', Georgia, Times, serif;
|
5
|
+
font-size: 20px;
|
6
|
+
line-height: 30px;
|
7
|
+
padding: 15px;
|
8
|
+
width: 720px;
|
9
|
+
|
10
|
+
}
|
11
|
+
header, footer, section, article {
|
12
|
+
display: block;
|
13
|
+
}
|
14
|
+
#content {
|
15
|
+
}
|
16
|
+
#by {
|
17
|
+
font-style: italic;
|
18
|
+
margin-right: 5px;
|
19
|
+
font-size: 28px;
|
20
|
+
}
|
21
|
+
#caption {
|
22
|
+
position: absolute;
|
23
|
+
font-size: 24px;
|
24
|
+
margin: -135px 0 0 70px;
|
25
|
+
}
|
26
|
+
#path {
|
27
|
+
color: #b53131;
|
28
|
+
}
|
29
|
+
.date {
|
30
|
+
font-style: italic;
|
31
|
+
float: right;
|
32
|
+
line-height: 43px;
|
33
|
+
margin-right: 30px;
|
34
|
+
}
|
35
|
+
a {
|
36
|
+
color: #b83000;
|
37
|
+
}
|
38
|
+
h1 a {
|
39
|
+
color: black;
|
40
|
+
text-decoration: none;
|
41
|
+
}
|
42
|
+
a:hover {
|
43
|
+
text-decoration: underline;
|
44
|
+
}
|
45
|
+
body > header > h1 {
|
46
|
+
border-left: 30px solid black;
|
47
|
+
padding-left: 30px;
|
48
|
+
font-size: 201px;
|
49
|
+
margin: 100px 0 15px 0;
|
50
|
+
font-weight: normal;
|
51
|
+
}
|
52
|
+
.post header {
|
53
|
+
margin-bottom: 10px;
|
54
|
+
}
|
55
|
+
.post .body p:first-child {
|
56
|
+
margin-top: 0;
|
57
|
+
}
|
58
|
+
.post .body p:last-child {
|
59
|
+
margin-bottom: 0;
|
60
|
+
}
|
61
|
+
.post {
|
62
|
+
margin-bottom: 30px;
|
63
|
+
}
|
64
|
+
.post:last-child {
|
65
|
+
margin-bottom: 10px;
|
66
|
+
}
|
67
|
+
.post p {
|
68
|
+
margin: 10px 0;
|
69
|
+
}
|
70
|
+
.post .more {
|
71
|
+
margin-top: -10px;
|
72
|
+
margin-right: 30px;
|
73
|
+
font-style: italic;
|
74
|
+
text-align: right;
|
75
|
+
}
|
76
|
+
.more a {
|
77
|
+
text-decoration: none;
|
78
|
+
}
|
79
|
+
.more a:hover { text-decoration: underline }
|
80
|
+
body > header {
|
81
|
+
display: block;
|
82
|
+
padding-top: 30px;
|
83
|
+
line-height: 180px;
|
84
|
+
margin-bottom: 20px;
|
85
|
+
}
|
86
|
+
h1, h2, h3, h4 {
|
87
|
+
display: inline;
|
88
|
+
margin: 0;
|
89
|
+
font-weight: 600;
|
90
|
+
}
|
91
|
+
ul, li {
|
92
|
+
list-style-type: none;
|
93
|
+
}
|
94
|
+
code {
|
95
|
+
font-family: 'Anonymous Pro', 'Bitstream Vera Sans', 'Monaco', Courier, mono;
|
96
|
+
}
|
97
|
+
pre {
|
98
|
+
padding: 20px;
|
99
|
+
}
|
100
|
+
blockquote {
|
101
|
+
font-style: italic;
|
102
|
+
}
|
103
|
+
|
104
|
+
body > footer {
|
105
|
+
text-align: left;
|
106
|
+
margin-left: 10px;
|
107
|
+
font-style: italic;
|
108
|
+
font-size: 18px;
|
109
|
+
color: #888;
|
110
|
+
}
|
@@ -0,0 +1,21 @@
|
|
1
|
+
xml.instruct!
|
2
|
+
xml.feed "xmlns" => "http://www.w3.org/2005/Atom" do
|
3
|
+
xml.title @config[:title]
|
4
|
+
xml.id @config[:url]
|
5
|
+
xml.updated articles.first[:date].iso8601 unless articles.empty?
|
6
|
+
xml.author { xml.name @config[:author] }
|
7
|
+
|
8
|
+
articles.reverse[0...10].each do |article|
|
9
|
+
xml.entry do
|
10
|
+
xml.title article.title
|
11
|
+
xml.link "rel" => "alternate", "href" => article.url
|
12
|
+
xml.id article.url
|
13
|
+
xml.published article[:date].iso8601
|
14
|
+
xml.updated article[:date].iso8601
|
15
|
+
xml.author { xml.name @config[:author] }
|
16
|
+
xml.summary article.summary, "type" => "html"
|
17
|
+
xml.content article.body, "type" => "html"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
@@ -0,0 +1,18 @@
|
|
1
|
+
<!doctype html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<link rel="stylesheet" type="text/css" href="/css/main.css">
|
5
|
+
<link rel="alternate" type="application/atom+xml" title="<%= title %> - feed" href="/index.xml" />
|
6
|
+
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
7
|
+
<title><%= title %></title>
|
8
|
+
</head>
|
9
|
+
<body>
|
10
|
+
<section>
|
11
|
+
<%= yield %>
|
12
|
+
</section>
|
13
|
+
<footer>
|
14
|
+
powered by <a href="http://cloudhead.io/toto">toto</a>
|
15
|
+
</footer>
|
16
|
+
</body>
|
17
|
+
</html>
|
18
|
+
|
File without changes
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<article class="post">
|
2
|
+
<header>
|
3
|
+
<h1><%= title %></h1>
|
4
|
+
<span class="date"><%= date %></span>
|
5
|
+
</header>
|
6
|
+
|
7
|
+
<section class="content">
|
8
|
+
<%= body %>
|
9
|
+
</section>
|
10
|
+
|
11
|
+
<section class="comments">
|
12
|
+
<% if @config[:disqus] %>
|
13
|
+
<div id="disqus_thread"></div>
|
14
|
+
<script type="text/javascript" src="http://disqus.com/forums/<%= @config[:disqus] %>/embed.js"> </script>
|
15
|
+
<noscript><a href="http://<%= @config[:disqus] %>.disqus.com/?url=ref">View the discussion thread.</a></noscript>
|
16
|
+
<a href="http://disqus.com" class="dsq-brlink">blog comments powered by <span class="logo-disqus">Disqus</span></a>
|
17
|
+
<% end %>
|
18
|
+
</section>
|
19
|
+
</article>
|
20
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<section id="articles">
|
2
|
+
<% for article in articles[0...3] %>
|
3
|
+
<article class="post">
|
4
|
+
<header>
|
5
|
+
<h1><a href="<%= article.path %>"><%= article.title %></a></h1>
|
6
|
+
<span class="date"><%= article.date %></span>
|
7
|
+
</header>
|
8
|
+
|
9
|
+
<section class="content">
|
10
|
+
<%= article.summary %>
|
11
|
+
</section>
|
12
|
+
<div class="more"><a href="<%= article.path %>">read on »</a></div>
|
13
|
+
</article>
|
14
|
+
<% end %>
|
15
|
+
</section>
|
16
|
+
|
17
|
+
<section id="archives">
|
18
|
+
<%= archives[3..-1] %>
|
19
|
+
</section>
|
20
|
+
|
metadata
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: allegro
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: true
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 0pre
|
9
|
+
version: 0.0.0pre
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Ermenegildo Fiorito
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-09-23 00:00:00 +02:00
|
18
|
+
default_executable:
|
19
|
+
dependencies: []
|
20
|
+
|
21
|
+
description: a pure ruby blog system based on cloudhead's toto
|
22
|
+
email: fiorito.g@gmail.com
|
23
|
+
executables:
|
24
|
+
- allegro
|
25
|
+
extensions: []
|
26
|
+
|
27
|
+
extra_rdoc_files: []
|
28
|
+
|
29
|
+
files:
|
30
|
+
- README.md
|
31
|
+
- lib/template/public/css/main.css
|
32
|
+
- lib/template/Rakefile
|
33
|
+
- lib/template/articles/1900-05-17-the-wonderful-wizard-of-oz.txt
|
34
|
+
- lib/template/templates/pages/article.rhtml
|
35
|
+
- lib/template/templates/pages/archives.rhtml
|
36
|
+
- lib/template/templates/pages/index.rhtml
|
37
|
+
- lib/template/templates/pages/about.rhtml
|
38
|
+
- lib/template/templates/index.builder
|
39
|
+
- lib/template/templates/layout.rhtml
|
40
|
+
- lib/template/config.ru
|
41
|
+
- lib/template/README
|
42
|
+
- lib/allegro.rb
|
43
|
+
- lib/allegro/version.rb
|
44
|
+
- lib/allegro/template.rb
|
45
|
+
- lib/allegro/site.rb
|
46
|
+
- lib/allegro/ext/ext.rb
|
47
|
+
- lib/allegro/context.rb
|
48
|
+
- lib/allegro/article.rb
|
49
|
+
- lib/allegro/archives.rb
|
50
|
+
- lib/allegro/server.rb
|
51
|
+
- lib/allegro/repo.rb
|
52
|
+
- bin/allegro
|
53
|
+
has_rdoc: true
|
54
|
+
homepage: http://github.com/fyskij/allegro
|
55
|
+
licenses: []
|
56
|
+
|
57
|
+
post_install_message: " \n \n ...of this astounding life down here\n and of the strange clowns in control of it\n\n -L. F.\n \n \n"
|
58
|
+
rdoc_options: []
|
59
|
+
|
60
|
+
require_paths:
|
61
|
+
- lib
|
62
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
63
|
+
none: false
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
segments:
|
68
|
+
- 0
|
69
|
+
version: "0"
|
70
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
71
|
+
none: false
|
72
|
+
requirements:
|
73
|
+
- - ">"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
segments:
|
76
|
+
- 1
|
77
|
+
- 3
|
78
|
+
- 1
|
79
|
+
version: 1.3.1
|
80
|
+
requirements: []
|
81
|
+
|
82
|
+
rubyforge_project:
|
83
|
+
rubygems_version: 1.3.7
|
84
|
+
signing_key:
|
85
|
+
specification_version: 3
|
86
|
+
summary: enjoy blogging
|
87
|
+
test_files: []
|
88
|
+
|