persona 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in persona.gemspec
4
+ gemspec
data/README.rdoc ADDED
@@ -0,0 +1,5 @@
1
+ == Persona
2
+
3
+ Persona is a minimal personal content manager.
4
+ In this stage it's a work in progress, without much documentation.
5
+
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
data/bin/persona ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+ require File.join(File.dirname(__FILE__), "..", "lib", "tasks", "persona_tasks")
3
+
4
+
5
+ def create_site(name)
6
+ p Dir.new('.').entries
7
+ end
8
+
9
+ if (ARGV.length == 2 and ARGV[0] == 'create_site')
10
+ PersonaTasks.create_site Dir.new('.'), ARGV[1]
11
+ end
12
+
@@ -0,0 +1,24 @@
1
+ require 'yaml'
2
+
3
+ class File
4
+
5
+ def content_as_string
6
+ doc_started = false
7
+ metadata, data = '', ''
8
+ self.each_line do |line|
9
+ doc_started = true if line.chop == ''
10
+ if (doc_started)
11
+ data += line
12
+ else
13
+ metadata +=line
14
+ end
15
+ end
16
+ @metadata = YAML.parse(metadata)
17
+ return data
18
+ end
19
+
20
+ def metadata(name)
21
+ @metadata[name].value
22
+ end
23
+
24
+ end
@@ -0,0 +1,13 @@
1
+ class Page
2
+
3
+ attr_reader :content, :title, :author
4
+
5
+ def initialize(name)
6
+ f = File.open("./contents/pages/#{name}.txt","r")
7
+ @content = f.content_as_string
8
+ @title = f.metadata 'title'
9
+ @author = f.metadata 'author'
10
+ f.close
11
+ end
12
+
13
+ end
@@ -0,0 +1,38 @@
1
+ class Post
2
+
3
+ attr_reader :content, :title, :author, :url, :date, :excerpt, :is_excerpt
4
+
5
+ def initialize(file_name)
6
+ f = File.open("./contents/posts/#{file_name}","r")
7
+ @content = f.content_as_string
8
+ @title = f.metadata 'title'
9
+ @author = f.metadata 'author'
10
+ @date = Date.strptime(f.metadata('date'), '%Y/%m/%d')
11
+ @excerpt = create_excerpt(@content)
12
+
13
+ splits = /(\d{4}-\d{2}-\d{2})-([^\/]*)\.txt$/.match file_name
14
+ if splits
15
+ @url = splits[1].gsub(/[-]/, "/") + "/" + splits[2] + "/"
16
+ end
17
+
18
+ f.close
19
+ end
20
+
21
+ def self.from_url(y,m,d,name)
22
+ Post.new "#{y}-#{m}-#{d}-#{name}.txt"
23
+ end
24
+
25
+ private
26
+
27
+ MORE_TAG = '<!--more-->'
28
+
29
+ def create_excerpt(content)
30
+ if content.include? MORE_TAG
31
+ @is_excerpt = true
32
+ content.partition(MORE_TAG)[0] + "(... continued ...) "
33
+ else
34
+ content
35
+ end
36
+ end
37
+
38
+ end
@@ -0,0 +1,3 @@
1
+ module Persona
2
+ VERSION = "0.0.1"
3
+ end
data/lib/persona.rb ADDED
@@ -0,0 +1,78 @@
1
+ require 'rubygems'
2
+ require 'erb'
3
+ require 'bundler'
4
+ require 'sinatra'
5
+ require 'builder'
6
+
7
+ require File.join(File.dirname(__FILE__), './persona', 'file')
8
+ autoload :Post, 'persona/post'
9
+ autoload :Page, 'persona/page'
10
+
11
+
12
+ #ROUTES
13
+
14
+ get '/' do
15
+ @posts = load_posts
16
+ erb :index
17
+ end
18
+
19
+ get '/feed/' do
20
+ builder do |xml|
21
+ xml.instruct! :xml, :version => '1.0'
22
+ xml.rss :version => "2.0" do
23
+ xml.channel do
24
+ xml.title ($config['site']['title'])
25
+ xml.description ($config['site']['description'])
26
+ xml.link ($config['site']['url'])
27
+
28
+ load_posts.first(10).each do |post|
29
+ xml.item do
30
+ xml.title post.title
31
+ xml.link(($config['site']['url'])+"/"+post.url)
32
+ xml.description post.content
33
+ xml.pubDate post.date.strftime("%a, %d %b %Y %H:%M:%S %z")
34
+ xml.guid(($config['site']['url'])+"/"+post.url)
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ get '/feed' do
43
+ redirect '/feed/'
44
+ end
45
+
46
+ get '/:y/:m/:d/:name/' do
47
+ @page = Post.from_url params[:y], params[:m], params[:d], params[:name]
48
+ erb :post
49
+ end
50
+
51
+ get '/:y/:m/:d/:name' do #wrong link, but WP supports it
52
+ redirect "/#{params[:y]}/#{params[:m]}/#{params[:d]}/#{params[:name]}/"
53
+ end
54
+
55
+ get '/pages/:name' do
56
+ @page = Page.new params[:name]
57
+ erb :page
58
+ end
59
+
60
+ error do
61
+ erb :not_found
62
+ end
63
+
64
+ not_found do
65
+ erb :not_found
66
+ end
67
+
68
+
69
+ def load_posts
70
+ posts = Dir.entries('./contents/posts').sort.reverse.reject do |it|
71
+ not it.end_with? '.txt'
72
+ end
73
+
74
+ posts.map do |it|
75
+ Post.new it
76
+ end
77
+ end
78
+
@@ -0,0 +1,10 @@
1
+ require 'fileutils'
2
+
3
+ class PersonaTasks
4
+
5
+ def self.create_site(base_dir, site_name)
6
+ FileUtils.cp_r(File.join(File.dirname(__FILE__), "..", "..", "template"), site_name)
7
+ end
8
+
9
+
10
+ end
data/persona.gemspec ADDED
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "persona/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "persona"
7
+ s.version = Persona::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Filippo Diotalevi"]
10
+ s.email = ["filippo.diotalevi@gmail.com"]
11
+ s.homepage = "https://github.com/fdiotalevi/persona-cms"
12
+ s.summary = %q{Minimal personal content manager}
13
+ s.description = %q{A minimal personal content manager}
14
+
15
+ s.add_dependency('sinatra', '>= 1.1.0')
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+ end
data/template/Gemfile ADDED
@@ -0,0 +1 @@
1
+ require 'persona'
@@ -0,0 +1,4 @@
1
+ site:
2
+ title: Filippo Diotalevi
3
+ description: Startups, Technology and News
4
+ url: 'http://diotalevi.com'
@@ -0,0 +1,9 @@
1
+ require 'sinatra'
2
+ require 'yaml'
3
+ require 'persona'
4
+
5
+ set :environment, :production
6
+ disable :run
7
+
8
+ $config = YAML.load_file('./config/persona.yaml')
9
+ run Sinatra::Application
@@ -0,0 +1,5 @@
1
+ title: about page
2
+ author: John Doe
3
+ date: 1900/01/01
4
+
5
+ <h1>About John</h1>
@@ -0,0 +1,5 @@
1
+ title: hello world
2
+ author: John Doe
3
+ date: 1900/01/01
4
+
5
+ <p>Hello world</p>
@@ -0,0 +1,108 @@
1
+ html { margin: 20px }
2
+ body {
3
+ margin: 0 auto;
4
+ font-family: Georgia, 'Baskerville', Times, serif;
5
+ font-size: 18px;
6
+ line-height: 27px;
7
+ padding: 15px;
8
+ width: 780px;
9
+
10
+ }
11
+ header, footer, section, article {
12
+ display: block;
13
+ }
14
+
15
+ body > header {
16
+ height: 30px;
17
+ font-size: 16px;
18
+ vertical-align: top;
19
+ margin-bottom: 60px;
20
+ }
21
+
22
+ #content {
23
+ }
24
+ #by {
25
+ font-style: italic;
26
+ margin-right: 5px;
27
+ font-size: 28px;
28
+ }
29
+ #caption {
30
+ position: absolute;
31
+ font-size: 24px;
32
+ margin: -135px 0 0 70px;
33
+ }
34
+ #path {
35
+ color: #b53131;
36
+ }
37
+ .date {
38
+ font-style: italic;
39
+ line-height: 43px;
40
+ }
41
+ a {
42
+ color: #b83000;
43
+ }
44
+ h1 a {
45
+ color: black;
46
+ text-decoration: none;
47
+ }
48
+ a:hover {
49
+ text-decoration: underline;
50
+ }
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
+
81
+ .spaced {
82
+ margin-bottom: 50px;
83
+ }
84
+
85
+ h1, h2, h3, h4 {
86
+ margin: 0;
87
+ font-weight: normal;
88
+ }
89
+ ul, li {
90
+ list-style-type: none;
91
+ }
92
+ code {
93
+ font-family: 'Anonymous Pro', 'Bitstream Vera Sans', 'Monaco', Courier, mono;
94
+ }
95
+ pre {
96
+ padding: 20px;
97
+ }
98
+ blockquote {
99
+ font-style: italic;
100
+ }
101
+
102
+ body > footer {
103
+ text-align: left;
104
+ margin-left: 10px;
105
+ font-style: italic;
106
+ font-size: 18px;
107
+ color: #888;
108
+ }
@@ -0,0 +1,26 @@
1
+
2
+ <% @posts.first(3).each do |page| %>
3
+
4
+ <div class="spaced">
5
+ <h1><a href="<%= page.url %>"><%= page.title %></a></h1>
6
+ <div class="date">published on <%= page.date.strftime('%b %d, %Y') %> by <%= page.author %>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div>
7
+
8
+ <%= page.excerpt %>
9
+
10
+ <% if page.is_excerpt %>
11
+ <div class="date"><a href="<%= page.url %>">Read the complete post</a></div>
12
+ <% end %>
13
+ </div>
14
+
15
+ <% end %>
16
+
17
+ <h2>Older posts</h2>
18
+ <ul>
19
+ <% if @posts.size > 3%>
20
+ <% @posts[3..-1].each do |post| %>
21
+ <li>
22
+ <a href="<%= post.url %>"><%= post.title %></a>, published on <%= post.date.strftime('%b %d, %Y') %>
23
+ </li>
24
+ <%end%>
25
+ <%end%>
26
+ </ul>
@@ -0,0 +1,41 @@
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="feed" href="/feed/" />
6
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
7
+ <title>Filippo Diotalevi</title>
8
+ <meta name="keywords" content="startup,technology,java,ruby,rails,osgi">
9
+ <meta name="author" content="Filippo Diotalevi">
10
+
11
+ <script type="text/javascript">
12
+
13
+ var _gaq = _gaq || [];
14
+ _gaq.push(['_setAccount', 'UA-398358-5']);
15
+ _gaq.push(['_trackPageview']);
16
+
17
+ (function() {
18
+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
19
+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
20
+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
21
+ })();
22
+
23
+ </script>
24
+
25
+
26
+ </head>
27
+ <body>
28
+ <header>
29
+ <a href='/'>Home</a> | <a href='/pages/about'>About</a>
30
+ </header>
31
+
32
+ <section>
33
+ <%= yield %>
34
+ </section>
35
+ <footer>
36
+ powered by Persona (unreleased yet), the minimal personal content manager
37
+ </footer>
38
+ </body>
39
+ </html>
40
+
41
+
@@ -0,0 +1,10 @@
1
+ <h1>Sorry, something went wrong</h1>
2
+ <p>
3
+ The page you request doesn't exist or couldn't be rendered.
4
+ <br/><br/>
5
+ </p>
6
+
7
+ <p>
8
+ <img src="http://dl.dropbox.com/u/1964762/diotalevi.com/images/404.jpg"/>
9
+
10
+ </p>
@@ -0,0 +1,4 @@
1
+ <h1><%= @page.title %></h1>
2
+ <div class="date">by <%= @page.author %></div>
3
+
4
+ <%= @page.content %>
@@ -0,0 +1,4 @@
1
+ <h1><%= @page.title %></h1>
2
+ <div class="date">published on <%= @page.date.strftime('%b %d, %Y') %> by <%= @page.author %>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div>
3
+
4
+ <%= @page.content %>
metadata ADDED
@@ -0,0 +1,101 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: persona
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ version: 0.0.1
10
+ platform: ruby
11
+ authors:
12
+ - Filippo Diotalevi
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2011-01-26 00:00:00 +01:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: sinatra
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 1
30
+ - 1
31
+ - 0
32
+ version: 1.1.0
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ description: A minimal personal content manager
36
+ email:
37
+ - filippo.diotalevi@gmail.com
38
+ executables:
39
+ - persona
40
+ extensions: []
41
+
42
+ extra_rdoc_files: []
43
+
44
+ files:
45
+ - .gitignore
46
+ - Gemfile
47
+ - README.rdoc
48
+ - Rakefile
49
+ - bin/persona
50
+ - lib/persona.rb
51
+ - lib/persona/file.rb
52
+ - lib/persona/page.rb
53
+ - lib/persona/post.rb
54
+ - lib/persona/version.rb
55
+ - lib/tasks/persona_tasks.rb
56
+ - persona.gemspec
57
+ - template/Gemfile
58
+ - template/config.ru
59
+ - template/config/persona.yaml
60
+ - template/contents/pages/about.txt
61
+ - template/contents/posts/1900-01-01-hello-world.txt
62
+ - template/public/css/main.css
63
+ - template/views/index.erb
64
+ - template/views/layout.erb
65
+ - template/views/not_found.erb
66
+ - template/views/page.erb
67
+ - template/views/post.erb
68
+ has_rdoc: true
69
+ homepage: https://github.com/fdiotalevi/persona-cms
70
+ licenses: []
71
+
72
+ post_install_message:
73
+ rdoc_options: []
74
+
75
+ require_paths:
76
+ - lib
77
+ required_ruby_version: !ruby/object:Gem::Requirement
78
+ none: false
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ segments:
83
+ - 0
84
+ version: "0"
85
+ required_rubygems_version: !ruby/object:Gem::Requirement
86
+ none: false
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ segments:
91
+ - 0
92
+ version: "0"
93
+ requirements: []
94
+
95
+ rubyforge_project:
96
+ rubygems_version: 1.3.7
97
+ signing_key:
98
+ specification_version: 3
99
+ summary: Minimal personal content manager
100
+ test_files: []
101
+