allegro 0.0.0pre
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|