0
0
Fork 0

restart blog by using zero and puma

This commit is contained in:
Gibheer 2013-08-05 21:51:23 +02:00
parent d6ec7051d7
commit 5e0b87164d
37 changed files with 31 additions and 1449 deletions

1
.rvmrc
View File

@ -1 +0,0 @@
rvm use default@zero-blog

23
Gemfile
View File

@ -1,21 +1,8 @@
source :rubygems
source 'https://rubygems.org'
gem 'rack', '1.3.6'
gem 'sinatra'
gem 'sinatra-support'
gem 'rack-flash'
gem 'haml'
gem 'puma'
gem 'zero', :git => 'https://github.com/libzero/zero.git'
gem 'slim'
gem 'sass'
gem 'compass'
gem 'data_mapper'
gem 'dm-postgres-adapter'
# the different markups
gem 'redclothcoderay'
gem 'coderay'
gem 'RedCloth'
gem 'redcarpet'
group :install do
gem 'highline'
end
gem 'kramdown'

View File

@ -1,96 +1,37 @@
GEM
remote: http://rubygems.org/
GIT
remote: https://github.com/libzero/zero.git
revision: d92dea46954b388ec13bc53c6e4f9894f25863c4
specs:
RedCloth (4.2.8)
addressable (2.2.6)
bcrypt-ruby (2.1.4)
chunky_png (1.2.5)
coderay (1.0.0)
compass (0.11.5)
zero (0.2.0)
tilt
GEM
remote: https://rubygems.org/
specs:
chunky_png (1.2.8)
compass (0.12.2)
chunky_png (~> 1.2)
fssm (>= 0.2.7)
sass (~> 3.1)
data_mapper (1.1.0)
dm-aggregates (= 1.1.0)
dm-constraints (= 1.1.0)
dm-core (= 1.1.0)
dm-migrations (= 1.1.0)
dm-serializer (= 1.1.0)
dm-timestamps (= 1.1.0)
dm-transactions (= 1.1.0)
dm-types (= 1.1.0)
dm-validations (= 1.1.0)
data_objects (0.10.6)
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)
fssm (0.2.10)
kramdown (1.1.0)
puma (2.4.0)
rack (>= 1.1, < 2.0)
rack (1.5.2)
sass (3.2.10)
slim (2.0.1)
temple (~> 0.6.6)
tilt (>= 1.3.3, < 2.1)
temple (0.6.6)
tilt (1.4.1)
PLATFORMS
ruby
DEPENDENCIES
RedCloth
coderay
compass
data_mapper
dm-postgres-adapter
haml
highline
rack-flash
redcarpet
redclothcoderay
kramdown
puma
sass
sinatra
sinatra-support
slim
zero!

15
README
View File

@ -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.

View File

@ -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
View File

@ -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

View File

@ -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
})

View File

32
libs.rb
View File

@ -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'

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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; } } }

View File

@ -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 */

View File

@ -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

View File

@ -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"

View File

@ -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'
)

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -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;
}
}

View File

@ -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

View File

@ -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

View File

@ -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(/</, '&lt;').gsub(/>/, '&gt;')
%content{:type => 'html'}=markup(post.content, post.markup).gsub(/</, '&lt;').gsub(/>/, '&gt;')

View File

@ -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}")}=">>"

View File

@ -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 &#169; 2011 by Gibheer and Stormwind"
:javascript
head.js(
'http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js',
'/public/app.js'
)

View File

@ -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)

View File

@ -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";