restart blog by using zero and puma
This commit is contained in:
parent
d6ec7051d7
commit
5e0b87164d
23
Gemfile
23
Gemfile
|
@ -1,21 +1,8 @@
|
||||||
source :rubygems
|
source 'https://rubygems.org'
|
||||||
|
|
||||||
gem 'rack', '1.3.6'
|
gem 'puma'
|
||||||
gem 'sinatra'
|
gem 'zero', :git => 'https://github.com/libzero/zero.git'
|
||||||
gem 'sinatra-support'
|
gem 'slim'
|
||||||
gem 'rack-flash'
|
|
||||||
gem 'haml'
|
|
||||||
gem 'sass'
|
gem 'sass'
|
||||||
gem 'compass'
|
gem 'compass'
|
||||||
gem 'data_mapper'
|
gem 'kramdown'
|
||||||
gem 'dm-postgres-adapter'
|
|
||||||
|
|
||||||
# the different markups
|
|
||||||
gem 'redclothcoderay'
|
|
||||||
gem 'coderay'
|
|
||||||
gem 'RedCloth'
|
|
||||||
gem 'redcarpet'
|
|
||||||
|
|
||||||
group :install do
|
|
||||||
gem 'highline'
|
|
||||||
end
|
|
||||||
|
|
111
Gemfile.lock
111
Gemfile.lock
|
@ -1,96 +1,37 @@
|
||||||
GEM
|
GIT
|
||||||
remote: http://rubygems.org/
|
remote: https://github.com/libzero/zero.git
|
||||||
|
revision: d92dea46954b388ec13bc53c6e4f9894f25863c4
|
||||||
specs:
|
specs:
|
||||||
RedCloth (4.2.8)
|
zero (0.2.0)
|
||||||
addressable (2.2.6)
|
tilt
|
||||||
bcrypt-ruby (2.1.4)
|
|
||||||
chunky_png (1.2.5)
|
GEM
|
||||||
coderay (1.0.0)
|
remote: https://rubygems.org/
|
||||||
compass (0.11.5)
|
specs:
|
||||||
|
chunky_png (1.2.8)
|
||||||
|
compass (0.12.2)
|
||||||
chunky_png (~> 1.2)
|
chunky_png (~> 1.2)
|
||||||
fssm (>= 0.2.7)
|
fssm (>= 0.2.7)
|
||||||
sass (~> 3.1)
|
sass (~> 3.1)
|
||||||
data_mapper (1.1.0)
|
fssm (0.2.10)
|
||||||
dm-aggregates (= 1.1.0)
|
kramdown (1.1.0)
|
||||||
dm-constraints (= 1.1.0)
|
puma (2.4.0)
|
||||||
dm-core (= 1.1.0)
|
rack (>= 1.1, < 2.0)
|
||||||
dm-migrations (= 1.1.0)
|
rack (1.5.2)
|
||||||
dm-serializer (= 1.1.0)
|
sass (3.2.10)
|
||||||
dm-timestamps (= 1.1.0)
|
slim (2.0.1)
|
||||||
dm-transactions (= 1.1.0)
|
temple (~> 0.6.6)
|
||||||
dm-types (= 1.1.0)
|
tilt (>= 1.3.3, < 2.1)
|
||||||
dm-validations (= 1.1.0)
|
temple (0.6.6)
|
||||||
data_objects (0.10.6)
|
tilt (1.4.1)
|
||||||
addressable (~> 2.1)
|
|
||||||
dm-aggregates (1.1.0)
|
|
||||||
dm-core (~> 1.1.0)
|
|
||||||
dm-constraints (1.1.0)
|
|
||||||
dm-core (~> 1.1.0)
|
|
||||||
dm-core (1.1.0)
|
|
||||||
addressable (~> 2.2.4)
|
|
||||||
dm-do-adapter (1.1.0)
|
|
||||||
data_objects (~> 0.10.2)
|
|
||||||
dm-core (~> 1.1.0)
|
|
||||||
dm-migrations (1.1.0)
|
|
||||||
dm-core (~> 1.1.0)
|
|
||||||
dm-postgres-adapter (1.1.0)
|
|
||||||
dm-do-adapter (~> 1.1.0)
|
|
||||||
do_postgres (~> 0.10.2)
|
|
||||||
dm-serializer (1.1.0)
|
|
||||||
dm-core (~> 1.1.0)
|
|
||||||
fastercsv (~> 1.5.4)
|
|
||||||
json (~> 1.4.6)
|
|
||||||
dm-timestamps (1.1.0)
|
|
||||||
dm-core (~> 1.1.0)
|
|
||||||
dm-transactions (1.1.0)
|
|
||||||
dm-core (~> 1.1.0)
|
|
||||||
dm-types (1.1.0)
|
|
||||||
bcrypt-ruby (~> 2.1.4)
|
|
||||||
dm-core (~> 1.1.0)
|
|
||||||
fastercsv (~> 1.5.4)
|
|
||||||
json (~> 1.4.6)
|
|
||||||
stringex (~> 1.2.0)
|
|
||||||
uuidtools (~> 2.1.2)
|
|
||||||
dm-validations (1.1.0)
|
|
||||||
dm-core (~> 1.1.0)
|
|
||||||
do_postgres (0.10.6)
|
|
||||||
data_objects (= 0.10.6)
|
|
||||||
fastercsv (1.5.4)
|
|
||||||
fssm (0.2.7)
|
|
||||||
haml (3.1.3)
|
|
||||||
highline (1.6.2)
|
|
||||||
json (1.4.6)
|
|
||||||
rack (1.3.3)
|
|
||||||
rack-flash (0.1.2)
|
|
||||||
rack
|
|
||||||
redcarpet (1.17.2)
|
|
||||||
redclothcoderay (0.3.6)
|
|
||||||
RedCloth
|
|
||||||
coderay
|
|
||||||
sass (3.1.7)
|
|
||||||
sinatra (1.2.6)
|
|
||||||
rack (~> 1.1)
|
|
||||||
tilt (>= 1.2.2, < 2.0)
|
|
||||||
sinatra-support (1.2.2)
|
|
||||||
sinatra (>= 1.0)
|
|
||||||
stringex (1.2.2)
|
|
||||||
tilt (1.3.3)
|
|
||||||
uuidtools (2.1.2)
|
|
||||||
|
|
||||||
PLATFORMS
|
PLATFORMS
|
||||||
ruby
|
ruby
|
||||||
|
|
||||||
DEPENDENCIES
|
DEPENDENCIES
|
||||||
RedCloth
|
|
||||||
coderay
|
|
||||||
compass
|
compass
|
||||||
data_mapper
|
kramdown
|
||||||
dm-postgres-adapter
|
puma
|
||||||
haml
|
|
||||||
highline
|
|
||||||
rack-flash
|
|
||||||
redcarpet
|
|
||||||
redclothcoderay
|
|
||||||
sass
|
sass
|
||||||
sinatra
|
slim
|
||||||
sinatra-support
|
zero!
|
||||||
|
|
15
README
15
README
|
@ -1,15 +0,0 @@
|
||||||
zero-blog
|
|
||||||
=========
|
|
||||||
|
|
||||||
After using jekyll for some time we decided, that it was not what we were looking
|
|
||||||
for. The idea itself was good, but it made writing blogs without a larger screen
|
|
||||||
impossible.
|
|
||||||
|
|
||||||
That's why we write our own blog system now. It stores the posts in a database
|
|
||||||
and will have an admin panel. That way, it's possible to write an entry from the
|
|
||||||
phone too.
|
|
||||||
|
|
||||||
Until now, it does not have many features apart from using datamapper and it
|
|
||||||
will likely not be the blog system you are looking for, without making some
|
|
||||||
changes for yourself, like the structure for the posts or the design. But maybe
|
|
||||||
you can build another system out of it.
|
|
72
Rakefile
72
Rakefile
|
@ -1,72 +0,0 @@
|
||||||
$LOAD_PATH << File.expand_path(File.dirname(__FILE__)) + '/'
|
|
||||||
|
|
||||||
def require_files
|
|
||||||
require 'libs'
|
|
||||||
require 'rake/functions'
|
|
||||||
end
|
|
||||||
|
|
||||||
namespace :dm do
|
|
||||||
desc 'migrate to the database model'
|
|
||||||
task :migrate do
|
|
||||||
require_files
|
|
||||||
require 'dm-migrations'
|
|
||||||
DataMapper.auto_migrate!
|
|
||||||
end
|
|
||||||
|
|
||||||
desc 'upgrade the database to the latest model'
|
|
||||||
task :upgrade do
|
|
||||||
require_files
|
|
||||||
require 'dm-migrations'
|
|
||||||
DataMapper.auto_upgrade!
|
|
||||||
end
|
|
||||||
|
|
||||||
desc 'fill the database with dummy data from seeds.rb'
|
|
||||||
task :seed do
|
|
||||||
require_files
|
|
||||||
require 'seeds'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
desc 'open a console with all libs loaded and a database connection opened'
|
|
||||||
task :console do
|
|
||||||
sh "irb -rubygems -I#{File.expand_path(File.dirname(__FILE__))} -r libs"
|
|
||||||
end
|
|
||||||
|
|
||||||
namespace :account do
|
|
||||||
desc 'create a new account'
|
|
||||||
task :create do
|
|
||||||
require_files
|
|
||||||
require 'highline'
|
|
||||||
h = HighLine.new
|
|
||||||
acc = Account.new
|
|
||||||
acc.username = h.ask('username: ')
|
|
||||||
acc.password = h.ask('password: '){|q| q.echo = false }
|
|
||||||
acc.password_confirmation = h.ask('password again: '){|q| q.echo = false }
|
|
||||||
acc.email = h.ask('email: ')
|
|
||||||
acc.role = :admin
|
|
||||||
if acc.save
|
|
||||||
puts "account saved with id #{acc.id}"
|
|
||||||
else
|
|
||||||
puts "failure at saving the account: #{acc.errors.first}"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
namespace :import do
|
|
||||||
desc 'import all posts from this directory'
|
|
||||||
task :jekyll do
|
|
||||||
require_files
|
|
||||||
path = ask("Where are the jekyll posts?")
|
|
||||||
template = ask("What is the default template? (textile, markdown, ...?)")
|
|
||||||
if path.nil?
|
|
||||||
puts "no path given! - aborting"
|
|
||||||
else
|
|
||||||
posts = Dir[path + '/*'].sort
|
|
||||||
if posts.empty?
|
|
||||||
puts "no posts in this directory"
|
|
||||||
else
|
|
||||||
import_jekyll posts, template
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
187
admin.rb
187
admin.rb
|
@ -1,187 +0,0 @@
|
||||||
class Admin < Sinatra::Base
|
|
||||||
set $settings
|
|
||||||
use Rack::Session::Pool, :expire_after => 1800
|
|
||||||
use Rack::Flash, :accessorize => [:error, :warning, :notice]
|
|
||||||
set :haml, :layout => :admin_layout
|
|
||||||
register Sinatra::CompassSupport
|
|
||||||
|
|
||||||
get '/' do
|
|
||||||
haml :admin_index
|
|
||||||
end
|
|
||||||
|
|
||||||
get '/post' do
|
|
||||||
@posts = Post.all(:order => [:id.desc], :limit => 15)
|
|
||||||
haml :admin_posts
|
|
||||||
end
|
|
||||||
|
|
||||||
get '/post/new' do
|
|
||||||
@post = Post.new
|
|
||||||
haml :admin_post_create
|
|
||||||
end
|
|
||||||
|
|
||||||
put '/post' do
|
|
||||||
if params[:post].has_key? 'tags'
|
|
||||||
tags = params[:post].delete('tags')
|
|
||||||
else
|
|
||||||
tags = []
|
|
||||||
end
|
|
||||||
@post = Post.new params[:post]
|
|
||||||
@post.set_tags tags
|
|
||||||
if @post.save
|
|
||||||
flash.notice = 'Post saved'
|
|
||||||
redirect "/admin/post/#{@post.id}", 303
|
|
||||||
else
|
|
||||||
flash.error = 'Error at saving the post'
|
|
||||||
flash[:errors] = @post.errors
|
|
||||||
redirect "/admin/post/new", 303
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
get '/post/:id' do
|
|
||||||
@post = Post.get(params[:id])
|
|
||||||
if @post
|
|
||||||
haml :admin_post_change
|
|
||||||
else
|
|
||||||
flash.warning = "Post with id #{params[:id]} not found!"
|
|
||||||
redirect './post', 303
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
post '/post/:id' do
|
|
||||||
# read the checkbox value
|
|
||||||
if params['post'].has_key?('released')
|
|
||||||
params['post']['released'] = true
|
|
||||||
else
|
|
||||||
params['post']['released'] = false
|
|
||||||
end
|
|
||||||
# get the post and update it
|
|
||||||
@post = Post.get(params[:id])
|
|
||||||
if @post
|
|
||||||
if params[:post].has_key? 'tags'
|
|
||||||
tags = params[:post].delete('tags')
|
|
||||||
end
|
|
||||||
if @post.update(params[:post])
|
|
||||||
@post.set_tags tags
|
|
||||||
@post.save
|
|
||||||
else
|
|
||||||
flash.warning = 'Error at saving the post!'
|
|
||||||
flash[:errors] = true
|
|
||||||
end
|
|
||||||
haml :admin_post_change
|
|
||||||
else
|
|
||||||
flash.warning = "Post with id #{params[:id]} not found!"
|
|
||||||
redirect './post', 303
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# tags
|
|
||||||
get '/tag' do
|
|
||||||
@tags = Tag.all(:order => [:name.asc])
|
|
||||||
haml :admin_tag_index
|
|
||||||
end
|
|
||||||
|
|
||||||
put '/tag/new' do
|
|
||||||
@tag = Tag.new(:name => params['tag']['name'])
|
|
||||||
if @tag.save
|
|
||||||
flash[:notice] = "Tag '#{@tag.name}' created!"
|
|
||||||
else
|
|
||||||
flash[:warning] = "Tag '#{@tag.name} could not be created! Error was: '#{@tag.errors.first}'"
|
|
||||||
end
|
|
||||||
redirect '/admin/tag', 303
|
|
||||||
end
|
|
||||||
|
|
||||||
get '/tag/:id' do
|
|
||||||
@tag = Tag.first(:id => params[:id])
|
|
||||||
haml :admin_tag_edit
|
|
||||||
end
|
|
||||||
|
|
||||||
post '/tag/:id' do
|
|
||||||
@tag = Tag.first(:id => params[:id])
|
|
||||||
@tag.name = params['tag']['name']
|
|
||||||
if @tag.save
|
|
||||||
flash[:notice] = "Tag saved"
|
|
||||||
redirect '/admin/tag', 303
|
|
||||||
else
|
|
||||||
flash[:notice] = "Tag could not be saved! Message: '#{@tag.errors.first}'"
|
|
||||||
haml :admin_tag_edit
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# login
|
|
||||||
get '/login' do
|
|
||||||
haml :admin_index_no_login
|
|
||||||
end
|
|
||||||
|
|
||||||
post '/login' do
|
|
||||||
account = Account.authenticate(params['username'], params['password'])
|
|
||||||
if account.nil?
|
|
||||||
flash.warning = 'wrong username or password'
|
|
||||||
flash[:username] = params['username']
|
|
||||||
redirect '/admin', 303
|
|
||||||
else
|
|
||||||
flash.notice = 'Login successful'
|
|
||||||
session[:id] = account.id
|
|
||||||
session[:last_updated] = Time.now
|
|
||||||
# redirect to the url set from the #before block
|
|
||||||
if session.has_key? :to_path
|
|
||||||
redirect "/admin#{session.delete(:to_path)}", 303
|
|
||||||
else
|
|
||||||
redirect '/admin/', 303
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
get '/logout' do
|
|
||||||
session[:id] = nil
|
|
||||||
session[:last_updated] = nil
|
|
||||||
flash.notice = 'Logout complete'
|
|
||||||
redirect '/'
|
|
||||||
end
|
|
||||||
|
|
||||||
get '/stylesheet.css' do
|
|
||||||
scss :admin_stylesheet
|
|
||||||
end
|
|
||||||
|
|
||||||
helpers do
|
|
||||||
def session_read
|
|
||||||
puts session.inspect
|
|
||||||
if (session.has_key?(:id) && session.has_key?(:last_updated) &&
|
|
||||||
Time.now - session[:last_updated] < 1800)
|
|
||||||
Account.get(session[:id])
|
|
||||||
else
|
|
||||||
nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def keys_to_sym hash
|
|
||||||
new_hash = {}
|
|
||||||
hash.each do |k, v|
|
|
||||||
new_hash[k.to_sym] = v
|
|
||||||
end
|
|
||||||
hash = new_hash
|
|
||||||
end
|
|
||||||
|
|
||||||
def markup content, markup
|
|
||||||
markup = markup.to_sym
|
|
||||||
if respond_to? markup
|
|
||||||
send markup, content
|
|
||||||
else
|
|
||||||
content
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
before do
|
|
||||||
@account = session_read
|
|
||||||
end
|
|
||||||
|
|
||||||
before %r{^(?!\/(login|stylesheet\.css)+$)} do
|
|
||||||
if @account.nil?
|
|
||||||
flash.warning = 'You are not logged in!'
|
|
||||||
session[:to_path] = request.path_info
|
|
||||||
redirect '/admin/login', 303
|
|
||||||
else
|
|
||||||
session[:last_updated] = Time.now
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
10
config.ru
10
config.ru
|
@ -1,10 +0,0 @@
|
||||||
$LOAD_PATH << File.expand_path(File.dirname(__FILE__)) + '/'
|
|
||||||
require 'libs'
|
|
||||||
|
|
||||||
use Rack::CommonLogger
|
|
||||||
use Rack::Deflater # compress with gzip
|
|
||||||
use Rack::Static, :urls => ['/public', '/images']
|
|
||||||
run Rack::URLMap.new({
|
|
||||||
'/' => Blog,
|
|
||||||
'/admin' => Admin
|
|
||||||
})
|
|
32
libs.rb
32
libs.rb
|
@ -1,32 +0,0 @@
|
||||||
# this file loads only the libs needed for using "something"
|
|
||||||
require 'rubygems'
|
|
||||||
require 'bundler/setup'
|
|
||||||
require 'bcrypt'
|
|
||||||
require 'data_mapper'
|
|
||||||
require 'haml'
|
|
||||||
require 'sass'
|
|
||||||
require 'compass'
|
|
||||||
require 'sinatra'
|
|
||||||
require 'sinatra/support'
|
|
||||||
require 'rack-flash'
|
|
||||||
|
|
||||||
# markups
|
|
||||||
require 'redcloth'
|
|
||||||
require 'redcarpet'
|
|
||||||
require 'coderay'
|
|
||||||
require 'redclothcoderay'
|
|
||||||
RedclothCoderay.coderay_options :css => :class
|
|
||||||
|
|
||||||
require 'settings'
|
|
||||||
|
|
||||||
# load the models
|
|
||||||
$LOAD_PATH << File.expand_path(File.dirname(__FILE__)) + '/models'
|
|
||||||
require 'account'
|
|
||||||
require 'post'
|
|
||||||
require 'comment'
|
|
||||||
require 'tag'
|
|
||||||
|
|
||||||
DataMapper.finalize
|
|
||||||
|
|
||||||
require 'page'
|
|
||||||
require 'admin'
|
|
|
@ -1,57 +0,0 @@
|
||||||
class Account
|
|
||||||
include DataMapper::Resource
|
|
||||||
include DataMapper::Validate
|
|
||||||
attr_accessor :password, :password_confirmation
|
|
||||||
|
|
||||||
# Properties
|
|
||||||
property :id, Serial
|
|
||||||
property :username, String, :lazy => false
|
|
||||||
property :email, String
|
|
||||||
property :crypted_password, String, :length => 70
|
|
||||||
property :role, String
|
|
||||||
|
|
||||||
has n, :posts
|
|
||||||
|
|
||||||
# Validations
|
|
||||||
validates_presence_of :username, :email, :role
|
|
||||||
validates_uniqueness_of :username, :case_sensitive => false
|
|
||||||
validates_presence_of :password, :if => :password_required
|
|
||||||
validates_presence_of :password_confirmation, :if => :password_required
|
|
||||||
validates_length_of :password, :min => 4, :max => 40, :if => :password_required
|
|
||||||
validates_confirmation_of :password, :if => :password_required
|
|
||||||
validates_length_of :email, :min => 3, :max => 100
|
|
||||||
validates_uniqueness_of :email, :case_sensitive => false
|
|
||||||
validates_format_of :email, :with => :email_address
|
|
||||||
validates_format_of :role, :with => /[A-Za-z]/
|
|
||||||
|
|
||||||
# Callbacks
|
|
||||||
before :save, :encrypt_password
|
|
||||||
|
|
||||||
##
|
|
||||||
# This method is for authentication purpose
|
|
||||||
#
|
|
||||||
def self.authenticate(username, password)
|
|
||||||
account = first(:conditions => { :username => username }) unless username.nil?
|
|
||||||
(account && account.has_password?(password)) ? account : nil
|
|
||||||
end
|
|
||||||
|
|
||||||
##
|
|
||||||
# This method is used by AuthenticationHelper
|
|
||||||
#
|
|
||||||
def self.find_by_id(id)
|
|
||||||
get(id) rescue nil
|
|
||||||
end
|
|
||||||
|
|
||||||
def has_password?(password)
|
|
||||||
::BCrypt::Password.new(crypted_password) == password
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
def password_required
|
|
||||||
crypted_password.nil? || password
|
|
||||||
end
|
|
||||||
|
|
||||||
def encrypt_password
|
|
||||||
self.crypted_password = ::BCrypt::Password.create(password) unless password.nil?
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,25 +0,0 @@
|
||||||
class Comment
|
|
||||||
include DataMapper::Resource
|
|
||||||
include DataMapper::Validate
|
|
||||||
|
|
||||||
property :id, Serial
|
|
||||||
property :author, String
|
|
||||||
property :email, String
|
|
||||||
property :acknowledged, Boolean, :default => false
|
|
||||||
property :body, Text
|
|
||||||
belongs_to :post
|
|
||||||
|
|
||||||
validates_presence_of :author, :email, :body
|
|
||||||
validates_length_of :email, :min => 3, :max => 100
|
|
||||||
validates_format_of :email, :with => :email_address
|
|
||||||
|
|
||||||
# overwrite the default to_json, because we don't need all fields
|
|
||||||
def to_json ressource_options
|
|
||||||
{
|
|
||||||
:id => id,
|
|
||||||
:post_id => post.id,
|
|
||||||
:author => author,
|
|
||||||
:body => body
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,51 +0,0 @@
|
||||||
class Post
|
|
||||||
include DataMapper::Resource
|
|
||||||
include DataMapper::Validate
|
|
||||||
|
|
||||||
property :id, Serial
|
|
||||||
property :title, Text, :required => true
|
|
||||||
property :written, Time, :default => lambda {|r, p| Time.now }
|
|
||||||
property :released, Boolean, :default => false
|
|
||||||
property :markup, Text, :default => 'textile'
|
|
||||||
property :content, Text
|
|
||||||
|
|
||||||
belongs_to :account
|
|
||||||
has n, :comments
|
|
||||||
has n, :tags, :through => Resource
|
|
||||||
|
|
||||||
def self.get_released id
|
|
||||||
get_all_released.get(id)
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.get_all_released
|
|
||||||
all(:released => true)
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.get_page page=0
|
|
||||||
get_all_released.all(:limit => 10, :offset => (page * 10),
|
|
||||||
:order => [:written.desc])
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.page_count
|
|
||||||
(get_all_released.count / 10).ceil
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.find_of_day time
|
|
||||||
get_all_released.all_written(time..(time+86400))
|
|
||||||
end
|
|
||||||
|
|
||||||
def acknowledged_comments
|
|
||||||
comments(:acknowledged => true)
|
|
||||||
end
|
|
||||||
|
|
||||||
# checks if a post has this tag
|
|
||||||
def has_tag tag
|
|
||||||
tag_id = tag.id
|
|
||||||
tags.any? { |t| t.id == tag_id }
|
|
||||||
end
|
|
||||||
|
|
||||||
# sets all tags for this post
|
|
||||||
def set_tags new_tags
|
|
||||||
self.tags = Tag.all(:id => new_tags)
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,11 +0,0 @@
|
||||||
class Tag
|
|
||||||
include DataMapper::Resource
|
|
||||||
include DataMapper::Validate
|
|
||||||
|
|
||||||
property :id, Serial
|
|
||||||
property :name, Text
|
|
||||||
|
|
||||||
has n, :posts, :through => Resource
|
|
||||||
validates_uniqueness_of :name, :case_sensitive => false
|
|
||||||
validates_presence_of :name
|
|
||||||
end
|
|
95
page.rb
95
page.rb
|
@ -1,95 +0,0 @@
|
||||||
class Blog < Sinatra::Base
|
|
||||||
set $settings
|
|
||||||
# never ever again load the Rack::Session::Pool here
|
|
||||||
# or the admin pool get's broken and you get thrown out after every request!
|
|
||||||
# do that in the config.ru, if you have to!
|
|
||||||
register Sinatra::CompassSupport
|
|
||||||
|
|
||||||
get '/' do
|
|
||||||
if params.has_key? 'page'
|
|
||||||
@current_page = params['page'].to_i
|
|
||||||
else
|
|
||||||
@current_page = 1
|
|
||||||
end
|
|
||||||
@page_count = Post.page_count
|
|
||||||
@posts = Post.get_page(@current_page - 1)
|
|
||||||
haml :index
|
|
||||||
end
|
|
||||||
|
|
||||||
get '/:year/:month/:day/:title.html' do
|
|
||||||
@post = Post.find_of_day(
|
|
||||||
Time.mktime(params[:year], params[:month], params[:day])
|
|
||||||
).select do |post|
|
|
||||||
params[:title] == post.title.gsub(/ /, '_').downcase
|
|
||||||
end
|
|
||||||
if @post.count > 0
|
|
||||||
@post = @post[0]
|
|
||||||
haml :post_single
|
|
||||||
else
|
|
||||||
404
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
get '/post/:id' do
|
|
||||||
@post = Post.get_released(params[:id])
|
|
||||||
if @post.nil?
|
|
||||||
404
|
|
||||||
else
|
|
||||||
haml :post_single
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
get '/post/:id/comment.json' do
|
|
||||||
Post.get_released(params[:id]).acknowledged_comments.to_json
|
|
||||||
end
|
|
||||||
|
|
||||||
get '/atom.xml' do
|
|
||||||
@posts = Post.get_page(0)
|
|
||||||
haml :atom, :layout => false
|
|
||||||
end
|
|
||||||
|
|
||||||
get '/stylesheet.css' do
|
|
||||||
scss :stylesheet
|
|
||||||
end
|
|
||||||
|
|
||||||
get '/404' do
|
|
||||||
404
|
|
||||||
end
|
|
||||||
|
|
||||||
error 404 do
|
|
||||||
'where am i? is somebody here? hello?'
|
|
||||||
end
|
|
||||||
|
|
||||||
get '/502' do
|
|
||||||
502
|
|
||||||
end
|
|
||||||
|
|
||||||
error 502 do
|
|
||||||
'oh no, i think i wet myself'
|
|
||||||
end
|
|
||||||
|
|
||||||
def link_to display, link
|
|
||||||
"<a href=\"${link}\">#{display}</a>"
|
|
||||||
end
|
|
||||||
|
|
||||||
def markup content, markup
|
|
||||||
markup = markup.to_sym
|
|
||||||
if respond_to? markup
|
|
||||||
send markup, content
|
|
||||||
else
|
|
||||||
content
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def domain path = ''
|
|
||||||
$settings[:domain] + path
|
|
||||||
end
|
|
||||||
|
|
||||||
def title
|
|
||||||
$settings[:title]
|
|
||||||
end
|
|
||||||
|
|
||||||
def subtitle
|
|
||||||
$settings[:subtitle]
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,4 +0,0 @@
|
||||||
$('a').live('click', function(e){
|
|
||||||
e.preventDefault();
|
|
||||||
$('#content').load($(this).attr('href') + ' #content');
|
|
||||||
})
|
|
File diff suppressed because one or more lines are too long
|
@ -1,66 +0,0 @@
|
||||||
require 'yaml'
|
|
||||||
|
|
||||||
def ask message
|
|
||||||
puts message
|
|
||||||
STDIN.gets.chomp
|
|
||||||
end
|
|
||||||
|
|
||||||
def import_jekyll files, template
|
|
||||||
# all tags used in the posts
|
|
||||||
template_tags = {}
|
|
||||||
post_tags = {}
|
|
||||||
puts "If asked about template tags, please give a replacement."
|
|
||||||
# from jekyll - lib/jekyll/convertible.rb#26 (08.2011)
|
|
||||||
files.each do |path|
|
|
||||||
content = File.read(path)
|
|
||||||
data = {}
|
|
||||||
if content =~ /^(---\s*\n.*?\n?)^(---\s*$\n?)/m
|
|
||||||
content = $POSTMATCH
|
|
||||||
|
|
||||||
begin
|
|
||||||
data = YAML.load($1)
|
|
||||||
rescue => e
|
|
||||||
puts "YAML exception reading #{path}: #{e.message}"
|
|
||||||
raise e
|
|
||||||
end
|
|
||||||
|
|
||||||
content = content.gsub /({{.*?}})/ do |m|
|
|
||||||
if template_tags.has_key? $1
|
|
||||||
template_tags[$1]
|
|
||||||
else
|
|
||||||
template_tags[$1] = ask("Found tag \"#{$1}\" in post #{data['title']}:")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
post = Post.new(
|
|
||||||
:written => data['date'],
|
|
||||||
:released => true,
|
|
||||||
:account => Account.first(:username => data['author']),
|
|
||||||
:markup => template,
|
|
||||||
:content => content,
|
|
||||||
:title => data['title']
|
|
||||||
)
|
|
||||||
if post.save
|
|
||||||
data['tags'].each do |t|
|
|
||||||
if (post_tags.has_key? t)
|
|
||||||
post_tags[t] << post
|
|
||||||
else
|
|
||||||
post_tags[t] = [post]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
puts "post #{post.title} of file #{path} could not be saved!"
|
|
||||||
end
|
|
||||||
else
|
|
||||||
puts "No valid jekyll file #{path}"
|
|
||||||
raise ArgumentError, "#{path} is not a jekyll file"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if post_tags.count > 0
|
|
||||||
post_tags.each do |tag_name, posts|
|
|
||||||
tag = Tag.new(:name => tag_name)
|
|
||||||
tag.posts = posts
|
|
||||||
tag.save
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
38
seeds.rb
38
seeds.rb
|
@ -1,38 +0,0 @@
|
||||||
gib = Account.new(
|
|
||||||
:username => 'Gibheer',
|
|
||||||
:password => 'food',
|
|
||||||
:password_confirmation => 'food',
|
|
||||||
:email => 'foo@bar.com',
|
|
||||||
:role => 'admin'
|
|
||||||
)
|
|
||||||
gib.save
|
|
||||||
storm = Account.new(
|
|
||||||
:username => 'Stormwind',
|
|
||||||
:password => 'bard',
|
|
||||||
:password_confirmation => 'bard',
|
|
||||||
:email => 'bar@foo.com',
|
|
||||||
:role => 'admin'
|
|
||||||
)
|
|
||||||
storm.save
|
|
||||||
|
|
||||||
(1..50).each do |i|
|
|
||||||
gib.posts.new(:title => "post #{i}", :content => "content of post #{i}",
|
|
||||||
:released => true).save
|
|
||||||
end
|
|
||||||
(1..50).each do |i|
|
|
||||||
storm.posts.new(:title => "post #{i}", :content => "content of post #{i}",
|
|
||||||
:released => true).save
|
|
||||||
end
|
|
||||||
storm.posts.new(:title => 'bar', :content => 'this is my post!').save
|
|
||||||
gib.posts.new(:title => 'foo', :content => 'this is mine!', :released => true).save
|
|
||||||
gib.posts.new(:title => 'lala', :content => 'lorem ipsum in the round about').save
|
|
||||||
storm.posts.new(:title => 'first!', :content => 'i\'m at the top!',
|
|
||||||
:released => true).save
|
|
||||||
Post.last.comments.new(:author => 'Gibheer', :email => 'foo@bar.com',
|
|
||||||
:acknowledged => true, :body => 'ipsum ipsum ipsum').save
|
|
||||||
gib.posts.new(:title => 'with markdown', :content => 'this is some `code`',
|
|
||||||
:markup => 'markdown', :released => true).save
|
|
||||||
Post.last.comments.new(:author => 'Gibheer', :email => 'foo@bar.com',
|
|
||||||
:acknowledged => false, :body => 'lorem lorem ipsum').save
|
|
||||||
Post.last.comments.new(:author => 'Stormwind', :email => 'bar@foo.com',
|
|
||||||
:acknowledged => true, :body => 'lorem ipsum').save
|
|
|
@ -1,21 +0,0 @@
|
||||||
$settings = {
|
|
||||||
:domain => 'http://example.com',
|
|
||||||
:title => 'zero-knowledge',
|
|
||||||
:subtitle => 'scripte, programmieren und administrtieren',
|
|
||||||
:environment => :development,
|
|
||||||
:logging => true,
|
|
||||||
:method_override => true,
|
|
||||||
:sass => {
|
|
||||||
:style => :expanded
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DataMapper::Logger.new($stdout, :debug) if $settings[:logging]
|
|
||||||
case $settings[:environment]
|
|
||||||
when :development then
|
|
||||||
DataMapper.setup(
|
|
||||||
:default, 'postgres://<user>:<passphrase>@localhost/<database>'
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
RedclothCoderay.coderay_options :css => :class
|
|
176
views/_base.scss
176
views/_base.scss
|
@ -1,176 +0,0 @@
|
||||||
header, article, section, aside, footer {
|
|
||||||
display: block;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0; }
|
|
||||||
|
|
||||||
html {
|
|
||||||
font-size: $font-size-base;
|
|
||||||
background: $background2; }
|
|
||||||
|
|
||||||
body {
|
|
||||||
font-size: $font-size;
|
|
||||||
font-family: $font-family;
|
|
||||||
color: $font-color1;
|
|
||||||
line-height: $font-size * 1.3;
|
|
||||||
min-width: $body-min-width;
|
|
||||||
max-width: $body-max-width;
|
|
||||||
margin: auto;
|
|
||||||
margin-top: $top-gap;
|
|
||||||
margin-bottom: $top-gap;
|
|
||||||
padding: 2em;
|
|
||||||
padding-top: 0;
|
|
||||||
background-color: $background1;
|
|
||||||
@include set-border-radius;
|
|
||||||
a {
|
|
||||||
color: $link-color1;
|
|
||||||
padding: 0.25em;
|
|
||||||
&:visited {
|
|
||||||
color: $link-color1; }
|
|
||||||
&:hover, &:active {
|
|
||||||
background-color: $highlight-color1;
|
|
||||||
@include set-border-radius;
|
|
||||||
@include background-image(linear-gradient($highlight-gradient)); } }
|
|
||||||
code {
|
|
||||||
font-family: $font-family-code; }
|
|
||||||
pre { margin: 1em; }
|
|
||||||
ul {
|
|
||||||
list-style-type: circle;
|
|
||||||
padding-left: 2em;
|
|
||||||
padding-bottom: 1em;
|
|
||||||
ul {
|
|
||||||
list-style-type: square;
|
|
||||||
ul {
|
|
||||||
list-style-type: disc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#wrapper {
|
|
||||||
margin-top: 5em; }
|
|
||||||
#header {
|
|
||||||
position: absolute;
|
|
||||||
width: 800px;
|
|
||||||
top: 0;
|
|
||||||
h1 {
|
|
||||||
> img {
|
|
||||||
margin-top: 2em; }
|
|
||||||
a {
|
|
||||||
font: {
|
|
||||||
size: $font-size * 4;
|
|
||||||
weight: bold; };
|
|
||||||
text-decoration: none;
|
|
||||||
padding: 0;
|
|
||||||
float: left;
|
|
||||||
text-shadow: 2px 5px 8px darken($background1, 10);
|
|
||||||
color: $link-color1;
|
|
||||||
&:hover, &:active {
|
|
||||||
background: none;
|
|
||||||
text-shadow: 3px 5px 8px darken($link-color1, 20); } } } }
|
|
||||||
#linklist {
|
|
||||||
border: 1px solid black;
|
|
||||||
float: right;
|
|
||||||
width: 250px; }
|
|
||||||
#content {
|
|
||||||
em {
|
|
||||||
font-style: oblique; }
|
|
||||||
strong {
|
|
||||||
font-weight: bold; }
|
|
||||||
i {
|
|
||||||
font-style: italic; }
|
|
||||||
b {
|
|
||||||
font-weight: bolder; }
|
|
||||||
cite {
|
|
||||||
font-style: italic; }
|
|
||||||
del {
|
|
||||||
text-decoration: line-through; }
|
|
||||||
ins {
|
|
||||||
text-decoration: underline; }
|
|
||||||
.float_left {
|
|
||||||
float: left;
|
|
||||||
margin: 4px; }
|
|
||||||
.float_right {
|
|
||||||
float: right;
|
|
||||||
margin: 4px; }
|
|
||||||
padding-top: $top-gap;
|
|
||||||
article {
|
|
||||||
clear: both;
|
|
||||||
margin-bottom: 1em;
|
|
||||||
padding-bottom: 0.5em;
|
|
||||||
@include set-border-with-radius;
|
|
||||||
@include clearfix;
|
|
||||||
section {
|
|
||||||
padding: 1em;
|
|
||||||
clear: left;
|
|
||||||
p {
|
|
||||||
margin-bottom: 1em; }
|
|
||||||
h1 {
|
|
||||||
font-size: $font-size * 1.3;
|
|
||||||
text-decoration: underline;
|
|
||||||
font-weight: bold;
|
|
||||||
margin-bottom: 3px; }
|
|
||||||
h2 {
|
|
||||||
font-size: $font-size * 1.2;
|
|
||||||
font-weight: bold;
|
|
||||||
magrin-bottom: 2px; } }
|
|
||||||
header {
|
|
||||||
float: left;
|
|
||||||
margin: 1em;
|
|
||||||
margin-bottom: 0;
|
|
||||||
h1 {
|
|
||||||
font-size: $font-size * 1.5;
|
|
||||||
font-weight: bold; } }
|
|
||||||
footer {
|
|
||||||
float: right;
|
|
||||||
width: 6.85em;
|
|
||||||
padding: 0.75em;
|
|
||||||
margin-left: 0.5em;
|
|
||||||
margin-bottom: 0.5em;
|
|
||||||
text-align: center;
|
|
||||||
// set the border
|
|
||||||
@include set-border-radius;
|
|
||||||
border-bottom: $border-width solid $border-color;
|
|
||||||
border-left: $border-width solid $border-color;
|
|
||||||
@include background-image(linear-gradient($background-gradient));
|
|
||||||
.author {
|
|
||||||
padding-bottom: 5px;
|
|
||||||
font-weight: bold; }
|
|
||||||
.date {
|
|
||||||
.day {
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: $font-size * 1.2; }
|
|
||||||
.month, .year {
|
|
||||||
font-size: $font-size * 0.75;
|
|
||||||
display: inline; } }
|
|
||||||
.time {
|
|
||||||
font-size: $font-size * 0.75;
|
|
||||||
.hour {
|
|
||||||
display: inline;
|
|
||||||
margin-right: -4px;
|
|
||||||
&:after {
|
|
||||||
content: ":"; } }
|
|
||||||
.minute {
|
|
||||||
display: inline; } } } }
|
|
||||||
.page {
|
|
||||||
text-align: center;
|
|
||||||
margin-bottom: 1em;
|
|
||||||
span.bold {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
a, span {
|
|
||||||
display: inline-block;
|
|
||||||
border: 1px solid black;
|
|
||||||
padding: 0.5em;
|
|
||||||
margin: 0;
|
|
||||||
width: 10%;
|
|
||||||
min-width: 90px;
|
|
||||||
@include set-border-radius;
|
|
||||||
@include box-sizing(border-box);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#footer {
|
|
||||||
padding: 1em;
|
|
||||||
overflow: hidden;
|
|
||||||
font-size: $font-size * 0.85;
|
|
||||||
@include set-border-with-radius;
|
|
||||||
p {
|
|
||||||
text-align: center; } } }
|
|
|
@ -1,64 +0,0 @@
|
||||||
.CodeRay {
|
|
||||||
font-family: $font-family-code;
|
|
||||||
//line-height: $font-size * 1.2;
|
|
||||||
background-color: #232323;
|
|
||||||
border: 1px solid black;
|
|
||||||
color: #E6E0DB;
|
|
||||||
padding: 3px 5px;
|
|
||||||
overflow: auto;
|
|
||||||
margin: 12px 0;
|
|
||||||
pre {
|
|
||||||
margin: 0px;
|
|
||||||
padding: 0px; }
|
|
||||||
.an {
|
|
||||||
color: #E7BE69; }
|
|
||||||
.c {
|
|
||||||
color: #BC9358;
|
|
||||||
font-style: italic; }
|
|
||||||
.ch {
|
|
||||||
color: #509E4F; }
|
|
||||||
.cl, .co {
|
|
||||||
color: #FFF; }
|
|
||||||
.fl {
|
|
||||||
color: #A4C260; }
|
|
||||||
.fu {
|
|
||||||
color: #FFC56D; }
|
|
||||||
.gv {
|
|
||||||
color: #D0CFFE; }
|
|
||||||
.i {
|
|
||||||
color: #A4C260; }
|
|
||||||
.il {
|
|
||||||
background: #151515; }
|
|
||||||
.iv {
|
|
||||||
color: #D0CFFE; }
|
|
||||||
.pp {
|
|
||||||
color: #E7BE69; }
|
|
||||||
.r {
|
|
||||||
color: #CB7832; }
|
|
||||||
.rx, .s {
|
|
||||||
color: #A4C260; }
|
|
||||||
.sy {
|
|
||||||
color: #6C9CBD; }
|
|
||||||
.ta {
|
|
||||||
color: #E7BE69; }
|
|
||||||
.pc {
|
|
||||||
color: #6C9CBD; } }
|
|
||||||
|
|
||||||
/* html attribute */
|
|
||||||
/* comment */
|
|
||||||
/* escaped character */
|
|
||||||
/* class */
|
|
||||||
/* constant */
|
|
||||||
/* float */
|
|
||||||
/* function */
|
|
||||||
/* global variable */
|
|
||||||
/* integer */
|
|
||||||
/* inline code */
|
|
||||||
/* instance variable */
|
|
||||||
/* doctype */
|
|
||||||
/* keyword */
|
|
||||||
/* regex */
|
|
||||||
/* string */
|
|
||||||
/* symbol */
|
|
||||||
/* html tag */
|
|
||||||
/* boolean */
|
|
|
@ -1,10 +0,0 @@
|
||||||
%a{:href => '/admin/logout'}="Logout"
|
|
||||||
%h1="Index"
|
|
||||||
#create
|
|
||||||
-@post = Post.new
|
|
||||||
=haml :admin_post_create, :layout => nil
|
|
||||||
%hr
|
|
||||||
#posts
|
|
||||||
%a{:href => '/admin/post'}="Posts"
|
|
||||||
-@posts=Post.all(:order => [:id.desc])
|
|
||||||
=haml :admin_posts, :layout => nil
|
|
|
@ -1,11 +0,0 @@
|
||||||
%form#login.fields{:action => '/admin/login', :method => 'post'}
|
|
||||||
.login="Welcome in the admin area."
|
|
||||||
.username
|
|
||||||
%label.block{:for => 'username'}='Username'
|
|
||||||
%input.block{:name => 'username', :placeholder => 'username', :value => flash[:username]}
|
|
||||||
.password
|
|
||||||
%label.block{:for => 'password'}='Password'
|
|
||||||
%input.block{:name => 'password', :placeholder => 'password', :type => :password}
|
|
||||||
.submit
|
|
||||||
%button{:type => 'submit'}="Login"
|
|
||||||
%button{:type => 'submit', :formmethod => :post, :formaction => '/'}="Back"
|
|
|
@ -1,31 +0,0 @@
|
||||||
!!! 5
|
|
||||||
%html
|
|
||||||
%head
|
|
||||||
%title="zero-knowledge - Adminpanel"
|
|
||||||
%link{:rel => 'stylesheet', :href => '/admin/stylesheet.css', :type => 'text/css'}
|
|
||||||
%script{:src => '/public/head.min.js'}
|
|
||||||
%body
|
|
||||||
#menu
|
|
||||||
%ul
|
|
||||||
%li
|
|
||||||
%a{:href => '/'}="main"
|
|
||||||
%li
|
|
||||||
%a{:href => '/admin'}="admin"
|
|
||||||
-if @account
|
|
||||||
%li
|
|
||||||
%a{:href => '/admin/post/new'}="create"
|
|
||||||
%li
|
|
||||||
%a{:href => '/admin/tag'}="tags"
|
|
||||||
#messages
|
|
||||||
-unless flash.error.nil?
|
|
||||||
%p.error=flash.error
|
|
||||||
-unless flash.warning.nil?
|
|
||||||
%p.warning=flash.warning
|
|
||||||
-unless flash.notice.nil?
|
|
||||||
%p.notice=flash.notice
|
|
||||||
#content=yield
|
|
||||||
:javascript
|
|
||||||
head.js(
|
|
||||||
'http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js',
|
|
||||||
'/public/admin.js'
|
|
||||||
)
|
|
|
@ -1,12 +0,0 @@
|
||||||
-unless @post.errors.nil?
|
|
||||||
-@post.errors.each do |error|
|
|
||||||
.error=error
|
|
||||||
%form{:action => "/admin/post/#{@post.id}", :method => :post}
|
|
||||||
.fields
|
|
||||||
=haml :admin_post_edit, :layout => nil
|
|
||||||
.buttons
|
|
||||||
%button{:type => :submit}="Update"
|
|
||||||
%button{:type => :submit, :formmethod => :get,
|
|
||||||
:formaction => '/admin/post'}="Back"
|
|
||||||
|
|
||||||
~haml :post_single, :layout => nil
|
|
|
@ -1,11 +0,0 @@
|
||||||
-if flash[:errors].nil?
|
|
||||||
-@post.errors.each do |error|
|
|
||||||
.error=error
|
|
||||||
%form{:action => "/admin/post", :method => :post}
|
|
||||||
.fields
|
|
||||||
%input{:type => :hidden, :name => "_method", :value => :put}=""
|
|
||||||
=(haml :admin_post_edit, :layout => nil)
|
|
||||||
.buttons
|
|
||||||
%button{:type => :submit}="Create"
|
|
||||||
%button{:type => :submit, :formmethod => :get,
|
|
||||||
:formaction => '/admin/post'}="Back"
|
|
|
@ -1,48 +0,0 @@
|
||||||
.main
|
|
||||||
.content
|
|
||||||
%label{:for => :post_content}="Content"
|
|
||||||
%textarea.content{:id => :post_content,
|
|
||||||
:name => 'post[content]'}=@post.content
|
|
||||||
.title
|
|
||||||
%label{:for => :post_title}="Title"
|
|
||||||
%input{:id => :post_title,
|
|
||||||
:name => 'post[title]',
|
|
||||||
:value => @post.title}
|
|
||||||
.further
|
|
||||||
.markup
|
|
||||||
%label{:for => :post_markup}="markup"
|
|
||||||
%select{:id => :post_markup, :name => 'post[markup]'}
|
|
||||||
-[:markdown, :textile].each do |markup|
|
|
||||||
-if @post.markup.to_sym == markup
|
|
||||||
%option{:selected => :selected}=markup
|
|
||||||
-else
|
|
||||||
%option=markup
|
|
||||||
.written
|
|
||||||
%label{:for => :post_written}="written"
|
|
||||||
%input{:id => :post_written,
|
|
||||||
:name => 'post[written]', :value => @post.written}
|
|
||||||
.released
|
|
||||||
%label{:for => :post_released}="released"
|
|
||||||
%input{:type => :checkbox, :name => 'post[released]',
|
|
||||||
:class => "post-released-#{@post.released}", :value => 0,
|
|
||||||
:checked => @post.released, :id => :post_released}
|
|
||||||
.author
|
|
||||||
%label{:for => :post_author}="Author"
|
|
||||||
%select{:name => 'post[account_id]', :id => :post_author}
|
|
||||||
-if @post.account.nil?
|
|
||||||
-@post.account = @account
|
|
||||||
-Account.all(:order => [:id]).each do |account|
|
|
||||||
-if @post.account.id == account.id
|
|
||||||
%option{:value => account.id, :selected => :selected}
|
|
||||||
=account.username
|
|
||||||
-else
|
|
||||||
%option{:value => account.id}=account.username
|
|
||||||
.tags
|
|
||||||
%label{:for => :post_tags}="Tags (#{Tag.all.count})"
|
|
||||||
%select{:name => 'post[tags][]', :id => :post_tags, :size => 10, :multiple => true}
|
|
||||||
- post_tags = @post.tags
|
|
||||||
- Tag.all(:order => [:name.asc]).each do |tag|
|
|
||||||
-if @post.has_tag tag
|
|
||||||
%option{:selected => :selected, :value => tag.id}=tag.name
|
|
||||||
-else
|
|
||||||
%option{:value => tag.id}=tag.name
|
|
|
@ -1,6 +0,0 @@
|
||||||
-@posts.each do |post|
|
|
||||||
.post
|
|
||||||
.title
|
|
||||||
%a{:href => "/admin/post/#{post.id}"}=post.title
|
|
||||||
%span.released{:class => "post-released-#{post.released}"}
|
|
||||||
.written=post.written
|
|
|
@ -1,151 +0,0 @@
|
||||||
// imports
|
|
||||||
@import "blueprint/colors";
|
|
||||||
@import "compass/reset";
|
|
||||||
@import "compass/css3";
|
|
||||||
@import "compass/utilities";
|
|
||||||
|
|
||||||
// variables
|
|
||||||
$font-color: hsl(0, 6%, 90%);
|
|
||||||
$link-color: $font-color;
|
|
||||||
$link-hover-color: hsl(32, 100%, 50%);
|
|
||||||
$border-color: black;
|
|
||||||
$background-normal: hsl(204, 25%, 35%);
|
|
||||||
$background-menu-normal: hsl(0, 0%, 20%);
|
|
||||||
$background-menu: color-stops(lighten($background-menu-normal, 15%),
|
|
||||||
$background-menu-normal 25%, darken($background-menu-normal, 15%));
|
|
||||||
$background-button: color-stops(lighten($background-normal, 15%),
|
|
||||||
$background-normal 75%, darken($background-normal, 5%));
|
|
||||||
$background-button-hover: color-stops(lighten($background-normal, 5%),
|
|
||||||
$background-normal 75%, darken($background-normal, 15%));
|
|
||||||
// some defaults for functions
|
|
||||||
$default-text-shadow-color: hsl(0, 10%, 50%);
|
|
||||||
$default-text-shadow-h-offset: 2px;
|
|
||||||
$default-text-shadow-v-offset: 2px;
|
|
||||||
$default-text-shadow-blur: 2px;
|
|
||||||
$default-border-radius: 2px;
|
|
||||||
|
|
||||||
body {background: $background-normal; color: $font-color;}
|
|
||||||
#menu, #messages, #content {
|
|
||||||
padding-left: 3em;
|
|
||||||
padding-right: 3em;
|
|
||||||
}
|
|
||||||
#messsages, #content {
|
|
||||||
padding-top: 1em;
|
|
||||||
}
|
|
||||||
#menu {
|
|
||||||
@include background-image(linear-gradient($background-menu));
|
|
||||||
li {
|
|
||||||
float: left;
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
:after {
|
|
||||||
content: '';
|
|
||||||
clear: both;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
a {
|
|
||||||
color: $link-color;
|
|
||||||
padding: 1em;
|
|
||||||
display: block;
|
|
||||||
text-decoration: none;
|
|
||||||
font-weight: bold;
|
|
||||||
@include single-text-shadow;
|
|
||||||
&:hover {
|
|
||||||
color: $link-hover-color;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#messages {
|
|
||||||
padding-top: 1em;
|
|
||||||
.message {
|
|
||||||
border: 1px solid black;
|
|
||||||
padding: 0.5em;
|
|
||||||
}
|
|
||||||
.error {
|
|
||||||
@extend .message;
|
|
||||||
background-color: $error-bg-color;
|
|
||||||
border-color: $error-border-color;
|
|
||||||
color: $error-color;
|
|
||||||
}
|
|
||||||
.warning {
|
|
||||||
@extend .message;
|
|
||||||
background-color: $notice-bg-color;
|
|
||||||
border-color: $notice-border-color;
|
|
||||||
color: $notice-color;
|
|
||||||
}
|
|
||||||
.notice {
|
|
||||||
@extend .message;
|
|
||||||
background-color: $success-bg-color;
|
|
||||||
border-color: $success-border-color;
|
|
||||||
color: $success-color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#content {
|
|
||||||
.buttons {
|
|
||||||
clear: both;
|
|
||||||
}
|
|
||||||
.fields {
|
|
||||||
clear: both;
|
|
||||||
.main {
|
|
||||||
width: 74%;
|
|
||||||
float: left;
|
|
||||||
textarea {
|
|
||||||
width: 100%;
|
|
||||||
height: 25em;
|
|
||||||
@include box-sizing(border-box);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.further {
|
|
||||||
float: right;
|
|
||||||
width: 24%;
|
|
||||||
}
|
|
||||||
.further:after {
|
|
||||||
content: '';
|
|
||||||
clear: both;
|
|
||||||
}
|
|
||||||
label, input, select {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
label {
|
|
||||||
font-size: 120%;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
input, select {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
button {
|
|
||||||
padding: 0.5em;
|
|
||||||
margin: 0.1em;
|
|
||||||
border: 1px solid $border-color;
|
|
||||||
color: $link-color;
|
|
||||||
font-weight: bold;
|
|
||||||
@include background-image(linear-gradient($background-button));
|
|
||||||
&:hover {
|
|
||||||
@include background-image(linear-gradient($background-button-hover));
|
|
||||||
}
|
|
||||||
&:active {
|
|
||||||
position: relative;
|
|
||||||
top: 1px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
a {
|
|
||||||
color: $link-color;
|
|
||||||
font: {
|
|
||||||
weight: bold;
|
|
||||||
decoration: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#login {
|
|
||||||
text-align: center;
|
|
||||||
.login {
|
|
||||||
padding: 1em;
|
|
||||||
font-weight: bold;
|
|
||||||
font-family: Sans;
|
|
||||||
}
|
|
||||||
> div {
|
|
||||||
width: 18em;
|
|
||||||
margin: auto;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
%form{:action => "/admin/tag/#{@tag.id}", :method => :post}
|
|
||||||
.fields
|
|
||||||
%input{:name => 'tag[name]', :placeholder => 'new tag name', :value => @tag.name}=""
|
|
||||||
.buttons
|
|
||||||
%button{:type => :submit}="update"
|
|
||||||
%ul
|
|
||||||
-@tag.posts.each do |post|
|
|
||||||
%li
|
|
||||||
%a{:href => "/admin/post/#{post.id}"}=post.title
|
|
|
@ -1,9 +0,0 @@
|
||||||
%form{:action => "/admin/tag/new", :method => :post}
|
|
||||||
%input{:type => :hidden, :name => '_method', :value => 'put'}=""
|
|
||||||
.fields
|
|
||||||
%input{:name => 'tag[name]', :placeholder => 'new tag name'}=""
|
|
||||||
.buttons
|
|
||||||
%button{:type => :submit}="create"
|
|
||||||
- @tags.each do |tag|
|
|
||||||
.tag
|
|
||||||
%a{:href => "/admin/tag/#{tag.id}"}=tag.name
|
|
|
@ -1,18 +0,0 @@
|
||||||
!!! XML
|
|
||||||
%feed{:xmlns => 'http://www.w3.org/2005/Atom'}
|
|
||||||
%title=title
|
|
||||||
%subtitle=subtitle
|
|
||||||
%link{:href => domain}
|
|
||||||
%link{:type => 'application/atom+xml', :rel => "self", :href => domain('/atom.xml')}
|
|
||||||
%updated=Post.get_all_released.last.written.xmlschema
|
|
||||||
%id=domain
|
|
||||||
-@posts.each do |post|
|
|
||||||
%entry
|
|
||||||
%id=domain("/post/#{post.id}")
|
|
||||||
%link{:type => 'text/html', :rel => "alternate", :href => "/post/#{post.id}"}
|
|
||||||
%title=post.title
|
|
||||||
%updated=post.written.xmlschema
|
|
||||||
%author
|
|
||||||
%name=post.account.username
|
|
||||||
%summary{:type => 'html'}=markup(post.content, post.markup).match(/.*?<\/p>/m)[0].gsub(/</, '<').gsub(/>/, '>')
|
|
||||||
%content{:type => 'html'}=markup(post.content, post.markup).gsub(/</, '<').gsub(/>/, '>')
|
|
|
@ -1,13 +0,0 @@
|
||||||
-@posts.each do |post|
|
|
||||||
-@post = post
|
|
||||||
=haml :post_single, :layout => nil
|
|
||||||
.page
|
|
||||||
-if @current_page > 2
|
|
||||||
%a{:href => domain('/?page=1')}="<<"
|
|
||||||
-if @current_page > 1
|
|
||||||
%a{:href => domain("/?page=#{@current_page - 1}")}="<"
|
|
||||||
%span.bold=@current_page
|
|
||||||
-if @current_page < @page_count + 1
|
|
||||||
%a{:href => domain("/?page=#{@current_page + 1}")}=">"
|
|
||||||
-if @current_page < (@page_count)
|
|
||||||
%a{:href => domain("/?page=#{@page_count + 1}")}=">>"
|
|
|
@ -1,24 +0,0 @@
|
||||||
!!! 5
|
|
||||||
%html
|
|
||||||
%head
|
|
||||||
%title="#{title} - #{subtitle}"
|
|
||||||
%meta{:'http-equiv' => 'Content-Type', :content => 'text/html; charset=utf-8'}
|
|
||||||
%link{:rel => 'stylesheet', :href => '/stylesheet.css', :type => 'text/css'}
|
|
||||||
%script{:src => domain('/public/javascript/head.min.js')}
|
|
||||||
%link{:rel => 'alternate', :type => 'application/atom+xml', :href => domain('/atom.xml'), :title => 'Atom 1.0'}
|
|
||||||
%body
|
|
||||||
#wrapper
|
|
||||||
%header#header
|
|
||||||
%h1
|
|
||||||
%a{:href => domain}
|
|
||||||
%img{:src => domain("/public/images/zero-knowledge.png"), :alt => title}
|
|
||||||
%img{:style => "float:right", :src => domain("/public/images/blub.png"), :alt => "Logo"}
|
|
||||||
#content
|
|
||||||
=yield
|
|
||||||
%footer#footer
|
|
||||||
%p="Design and Content © 2011 by Gibheer and Stormwind"
|
|
||||||
:javascript
|
|
||||||
head.js(
|
|
||||||
'http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js',
|
|
||||||
'/public/app.js'
|
|
||||||
)
|
|
|
@ -1,14 +0,0 @@
|
||||||
%article
|
|
||||||
%header
|
|
||||||
%h1
|
|
||||||
%a{:href => domain("/post/#{@post.id}")}=@post.title
|
|
||||||
%footer
|
|
||||||
.author=@post.account.username
|
|
||||||
.date
|
|
||||||
.day=@post.written.strftime('%d')
|
|
||||||
.month=@post.written.strftime('%B')
|
|
||||||
.year=@post.written.strftime('%Y')
|
|
||||||
.time
|
|
||||||
.hour=@post.written.strftime('%H')
|
|
||||||
.minute=@post.written.strftime('%M')
|
|
||||||
%section~markup(@post.content, @post.markup)
|
|
|
@ -1,46 +0,0 @@
|
||||||
//colors
|
|
||||||
$font-color1: hsl(0, 0%, 95%);
|
|
||||||
$link-color1: hsl(32, 100%, 50%);
|
|
||||||
$highlight-color1: hsl(204, 33%, 45%);
|
|
||||||
$highlight-gradient: color-stops(lighten($highlight-color1, 5), $highlight-color1 30%, darken($highlight-color1, 15));
|
|
||||||
$border-color: black;
|
|
||||||
$background1: hsl(204, 25%, 35%);
|
|
||||||
$background2: hsl(0, 0%, 20%);
|
|
||||||
$background-gradient: color-stops(lighten($background1, 5), $background1 25%, darken($background1, 5));
|
|
||||||
|
|
||||||
// font
|
|
||||||
$font-size: 100%;
|
|
||||||
$font-size-base: 14px;
|
|
||||||
$font-family: "DejaVu Sans", Verdana, Arial, sans-serif;
|
|
||||||
$font-family-code: monospace;
|
|
||||||
|
|
||||||
//$font-family: 'Droid Serif', 'DejaVu Serif', 'Bitstream Vera Serif', Serif
|
|
||||||
//$font-family-code: 'Droid Mono', 'Courier New', 'Terminal', monospace
|
|
||||||
// sizes
|
|
||||||
// -- body
|
|
||||||
$body-min-width: 400px;
|
|
||||||
$body-max-width: 900px;
|
|
||||||
$top-gap: 95px;
|
|
||||||
|
|
||||||
// -- border stuff
|
|
||||||
$border-width: 1px;
|
|
||||||
$border-radius: 4px;
|
|
||||||
|
|
||||||
//imports
|
|
||||||
@import "compass/reset";
|
|
||||||
@import "compass/css3";
|
|
||||||
@import "compass/utilities";
|
|
||||||
|
|
||||||
// build own mixins
|
|
||||||
@mixin set-border {
|
|
||||||
border: $border-width solid $border-color; }
|
|
||||||
|
|
||||||
@mixin set-border-radius {
|
|
||||||
@include border-radius($border-radius, $border-radius); }
|
|
||||||
|
|
||||||
@mixin set-border-with-radius {
|
|
||||||
@include set-border;
|
|
||||||
@include set-border-radius; }
|
|
||||||
|
|
||||||
@import "base";
|
|
||||||
@import "coderay";
|
|
Loading…
Reference in New Issue