hobix 0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/bin/hobix +90 -0
- data/lib/hobix/api.rb +91 -0
- data/lib/hobix/article.rb +22 -0
- data/lib/hobix/base.rb +477 -0
- data/lib/hobix/bixwik.rb +200 -0
- data/lib/hobix/commandline.rb +661 -0
- data/lib/hobix/comments.rb +99 -0
- data/lib/hobix/config.rb +39 -0
- data/lib/hobix/datamarsh.rb +110 -0
- data/lib/hobix/entry.rb +83 -0
- data/lib/hobix/facets/comments.rb +74 -0
- data/lib/hobix/facets/publisher.rb +314 -0
- data/lib/hobix/facets/trackbacks.rb +80 -0
- data/lib/hobix/linklist.rb +76 -0
- data/lib/hobix/out/atom.rb +92 -0
- data/lib/hobix/out/erb.rb +64 -0
- data/lib/hobix/out/okaynews.rb +55 -0
- data/lib/hobix/out/quick.rb +312 -0
- data/lib/hobix/out/rdf.rb +97 -0
- data/lib/hobix/out/redrum.rb +26 -0
- data/lib/hobix/out/rss.rb +115 -0
- data/lib/hobix/plugin/bloglines.rb +73 -0
- data/lib/hobix/plugin/calendar.rb +220 -0
- data/lib/hobix/plugin/flickr.rb +110 -0
- data/lib/hobix/plugin/recent_comments.rb +82 -0
- data/lib/hobix/plugin/sections.rb +91 -0
- data/lib/hobix/plugin/tags.rb +60 -0
- data/lib/hobix/publish/ping.rb +53 -0
- data/lib/hobix/publish/replicate.rb +283 -0
- data/lib/hobix/publisher.rb +18 -0
- data/lib/hobix/search/dictionary.rb +141 -0
- data/lib/hobix/search/porter_stemmer.rb +203 -0
- data/lib/hobix/search/simple.rb +209 -0
- data/lib/hobix/search/vector.rb +100 -0
- data/lib/hobix/storage/filesys.rb +398 -0
- data/lib/hobix/trackbacks.rb +94 -0
- data/lib/hobix/util/objedit.rb +193 -0
- data/lib/hobix/util/patcher.rb +155 -0
- data/lib/hobix/webapp/cli.rb +195 -0
- data/lib/hobix/webapp/htmlform.rb +107 -0
- data/lib/hobix/webapp/message.rb +177 -0
- data/lib/hobix/webapp/urigen.rb +141 -0
- data/lib/hobix/webapp/webrick-servlet.rb +90 -0
- data/lib/hobix/webapp.rb +723 -0
- data/lib/hobix/weblog.rb +860 -0
- data/lib/hobix.rb +223 -0
- metadata +87 -0
@@ -0,0 +1,99 @@
|
|
1
|
+
#
|
2
|
+
# = hobix/comments.rb
|
3
|
+
#
|
4
|
+
# Hobix command-line weblog system, API for comments.
|
5
|
+
#
|
6
|
+
# Copyright (c) 2003-2004 why the lucky stiff
|
7
|
+
#
|
8
|
+
# Written & maintained by why the lucky stiff <why@ruby-lang.org>
|
9
|
+
#
|
10
|
+
# This program is free software, released under a BSD license.
|
11
|
+
# See COPYING for details.
|
12
|
+
#
|
13
|
+
#--
|
14
|
+
# $Id$
|
15
|
+
#++
|
16
|
+
|
17
|
+
require 'hobix/facets/comments'
|
18
|
+
|
19
|
+
module Hobix
|
20
|
+
module Out
|
21
|
+
class Quick
|
22
|
+
append_def :head_tags_erb, %{
|
23
|
+
<meta http-equiv="Pragma" content="no-cache" />
|
24
|
+
<meta http-equiv="Expires" content="-1" />
|
25
|
+
<script type="text/javascript" src="<%= weblog.expand_path( '/js/prototype.js' ) %>"></script>
|
26
|
+
<script type="text/javascript">
|
27
|
+
function quickRedReference() {
|
28
|
+
window.open(
|
29
|
+
"http://hobix.com/textile/quick.html",
|
30
|
+
"redRef",
|
31
|
+
"height=600,width=550,channelmode=0,dependent=0," +
|
32
|
+
"directories=0,fullscreen=0,location=0,menubar=0," +
|
33
|
+
"resizable=0,scrollbars=1,status=1,toolbar=0"
|
34
|
+
);
|
35
|
+
}
|
36
|
+
</script>
|
37
|
+
}
|
38
|
+
|
39
|
+
append_def :entry_erb, %{
|
40
|
+
<% if entry and not defined? entries %>
|
41
|
+
<+ entry_comment +>
|
42
|
+
<+ entry_comment_form +>
|
43
|
+
<% end %>
|
44
|
+
}
|
45
|
+
|
46
|
+
def entry_comment_erb; %{
|
47
|
+
<% entry_id = entry.id %>
|
48
|
+
<a name="comments"></a>
|
49
|
+
<div id="comments">
|
50
|
+
<% comments = weblog.storage.load_attached( entry_id, "comments" ) rescue [] %>
|
51
|
+
<% comments.each do |comment| %>
|
52
|
+
<div class="entry">
|
53
|
+
<div class="entryAttrib">
|
54
|
+
<div class="entryAuthor"><h3><%= comment.author %></h3></div>
|
55
|
+
<div class="entryTime">said on <%= comment.created.strftime( "<nobr>%d %b %Y</nobr> at <nobr>%I:%M %p</nobr>" ) %></div>
|
56
|
+
</div>
|
57
|
+
<div class="entryContentOuter"><div class="entryContent"><%= comment.content.to_html %></div></div>
|
58
|
+
</div>
|
59
|
+
<% end %>
|
60
|
+
} end
|
61
|
+
|
62
|
+
def entry_comment_form_erb; %{
|
63
|
+
<div class="entry">
|
64
|
+
<form id="userComment" method="post" action="/control/comment/<%= entry_id %>">
|
65
|
+
<div class="entryAttrib">
|
66
|
+
<div class="entryAuthor"><input name="<%= Hobix::Facets::Comments.form_field 'author' %>" type="textbox" size="15" maxlength="50" /></div>
|
67
|
+
<div id="liveTime" class="entryTime">said on <nobr>DD Mon YYYY</nobr> <nobr>at HH:MM AM</nobr></div>
|
68
|
+
</div>
|
69
|
+
<div class="entryContentOuter"><div class="entryContent">
|
70
|
+
<textarea name="<%= Hobix::Facets::Comments.form_field 'content' %>" rows="6" cols="50"></textarea>
|
71
|
+
<p><input type="button" name="pleasePreview" value="preview"
|
72
|
+
onClick="new Ajax.Request('/control/preview', {parameters: Form.serialize('userComment'), onComplete: function(req) { $('textilePreview').innerHTML = req.responseText }})" />
|
73
|
+
<input type="submit" name="<%= Hobix::Facets::Comments.form_field 'submit' %>" value=">>" />
|
74
|
+
<small>* do <a href="javascript:quickRedReference();">fancy stuff</a> in your comment.</small>
|
75
|
+
</p>
|
76
|
+
<div id="textileWrap"><!-- <h4>PREVIEW PANE</h4> -->
|
77
|
+
<div id="textilePreview"></div>
|
78
|
+
</div>
|
79
|
+
</div>
|
80
|
+
</div></div>
|
81
|
+
|
82
|
+
</form>
|
83
|
+
</div>
|
84
|
+
} end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
class Comment < BaseContent
|
89
|
+
_! "Comment Information"
|
90
|
+
_ :author, :req => true, :edit_as => :text, :search => :prefix
|
91
|
+
_ :created, :edit_as => :datetime
|
92
|
+
_ :url, :edit_as => :text
|
93
|
+
_ :email, :edit_as => :text
|
94
|
+
_ :content, :edit_as => :textarea, :search => :fulltext, :text_processor => true
|
95
|
+
_ :ipaddress, :edit_as => :text
|
96
|
+
|
97
|
+
yaml_type "tag:hobix.com,2005:comment"
|
98
|
+
end
|
99
|
+
end
|
data/lib/hobix/config.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
#
|
2
|
+
# = hobix/config.rb
|
3
|
+
#
|
4
|
+
# Hobix command-line weblog system.
|
5
|
+
#
|
6
|
+
# Copyright (c) 2003-2004 why the lucky stiff
|
7
|
+
#
|
8
|
+
# Written & maintained by why the lucky stiff <why@ruby-lang.org>
|
9
|
+
#
|
10
|
+
# This program is free software, released under a BSD license.
|
11
|
+
# See COPYING for details.
|
12
|
+
#
|
13
|
+
#--
|
14
|
+
# $Id$
|
15
|
+
#++
|
16
|
+
|
17
|
+
require 'yaml'
|
18
|
+
|
19
|
+
module Hobix
|
20
|
+
class Config
|
21
|
+
attr_accessor :weblogs, :username, :personal,
|
22
|
+
:post_upgen, :use_editor
|
23
|
+
def initialize
|
24
|
+
@username = ENV['USER'] unless @username
|
25
|
+
self
|
26
|
+
end
|
27
|
+
def Config.load( conf_file )
|
28
|
+
c = YAML::load( File::open( conf_file ) )
|
29
|
+
c.keys.each do |k|
|
30
|
+
if k =~ /\s/
|
31
|
+
k_ = k.gsub( /\s/, '_' )
|
32
|
+
c[k_] = c.delete( k )
|
33
|
+
end
|
34
|
+
end
|
35
|
+
c = YAML::object_maker( Hobix::Config, c )
|
36
|
+
c.initialize
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
require 'dbm'
|
2
|
+
#
|
3
|
+
# Marshal + DBM = DataMarsh
|
4
|
+
# - Same interface as DBM class
|
5
|
+
#
|
6
|
+
module Hobix
|
7
|
+
|
8
|
+
class DataMarsh < ::DBM
|
9
|
+
VERSION = "0.1"
|
10
|
+
def []( key )
|
11
|
+
fetch( key )
|
12
|
+
end
|
13
|
+
def []=( key, val )
|
14
|
+
store( key, val )
|
15
|
+
end
|
16
|
+
def fetch( keystr, ifnone = nil )
|
17
|
+
begin
|
18
|
+
val = super( keystr )
|
19
|
+
return Marshal::load( val ) if String === val
|
20
|
+
rescue IndexError
|
21
|
+
end
|
22
|
+
if block_given?
|
23
|
+
yield keystr
|
24
|
+
else
|
25
|
+
ifnone
|
26
|
+
end
|
27
|
+
end
|
28
|
+
def index( keystr )
|
29
|
+
super( keystr.to_yaml )
|
30
|
+
end
|
31
|
+
def values_at( *keys )
|
32
|
+
keys.collect { |k| fetch( k ) }
|
33
|
+
end
|
34
|
+
def delete( key )
|
35
|
+
v = super( key )
|
36
|
+
if String === v
|
37
|
+
v = Marshal::load( v )
|
38
|
+
end
|
39
|
+
v
|
40
|
+
end
|
41
|
+
def delete_if
|
42
|
+
del_keys = keys.dup
|
43
|
+
del_keys.delete_if { |k| yield( k, fetch( k ) ) == false }
|
44
|
+
del_keys.each { |k| delete( k ) }
|
45
|
+
self
|
46
|
+
end
|
47
|
+
def reject
|
48
|
+
hsh = self.to_hash
|
49
|
+
hsh.reject { |k,v| yield k, v }
|
50
|
+
end
|
51
|
+
def each_pair
|
52
|
+
keys.each { |k| yield k, fetch( k ) }
|
53
|
+
self
|
54
|
+
end
|
55
|
+
def each_value
|
56
|
+
super { |v| yield Marshal::load( v ) }
|
57
|
+
self
|
58
|
+
end
|
59
|
+
def values
|
60
|
+
super.collect { |v| Marshal::load( v ) }
|
61
|
+
end
|
62
|
+
def has_value?( val )
|
63
|
+
each_value { |v| return true if v == val }
|
64
|
+
return false
|
65
|
+
end
|
66
|
+
def invert
|
67
|
+
h = {}
|
68
|
+
keys.each { |k| h[ self.fetch( k ) ] = k }
|
69
|
+
h
|
70
|
+
end
|
71
|
+
def replace( hsh )
|
72
|
+
clear
|
73
|
+
update( hsh )
|
74
|
+
end
|
75
|
+
def shift
|
76
|
+
a = super
|
77
|
+
a[1] = Marshal::load( a[1] ) if a
|
78
|
+
a
|
79
|
+
end
|
80
|
+
def select( *keys )
|
81
|
+
if block_given?
|
82
|
+
self.keys.collect { |k| v = self[k]; [k, v] if yield k, v }.compact
|
83
|
+
else
|
84
|
+
values_at( *keys )
|
85
|
+
end
|
86
|
+
end
|
87
|
+
def store( key, val )
|
88
|
+
super( key, val.to_yaml )
|
89
|
+
val
|
90
|
+
end
|
91
|
+
def update( hsh )
|
92
|
+
hsh.keys.each do |k|
|
93
|
+
self.store( k, hsh.fetch( k ) )
|
94
|
+
end
|
95
|
+
self
|
96
|
+
end
|
97
|
+
def to_a
|
98
|
+
a = []
|
99
|
+
keys.each { |k| a.push [ k, self.fetch( k ) ] }
|
100
|
+
a
|
101
|
+
end
|
102
|
+
def to_hash
|
103
|
+
h = {}
|
104
|
+
keys.each { |k| h[ k ] = self.fetch( k ) }
|
105
|
+
h
|
106
|
+
end
|
107
|
+
alias :each :each_pair
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
data/lib/hobix/entry.rb
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
#
|
2
|
+
# = hobix/entry.rb
|
3
|
+
#
|
4
|
+
# Hobix command-line weblog system.
|
5
|
+
#
|
6
|
+
# Copyright (c) 2003-2004 why the lucky stiff
|
7
|
+
#
|
8
|
+
# Written & maintained by why the lucky stiff <why@ruby-lang.org>
|
9
|
+
#
|
10
|
+
# This program is free software, released under a BSD license.
|
11
|
+
# See COPYING for details.
|
12
|
+
#
|
13
|
+
#--
|
14
|
+
# $Id$
|
15
|
+
#++
|
16
|
+
|
17
|
+
module Hobix
|
18
|
+
# The Entry class stores complete data for an entry on the site. All
|
19
|
+
# entry extensions should behave like this class as well.
|
20
|
+
#
|
21
|
+
# == Properties
|
22
|
+
#
|
23
|
+
# At the very least, entry data should support the following
|
24
|
+
# accessors.
|
25
|
+
#
|
26
|
+
# id:: The id (or shortName) for this entry. Includes
|
27
|
+
# the basic entry path.
|
28
|
+
# link:: The full URL to this entry from the weblog.
|
29
|
+
# title:: The heading for this entry.
|
30
|
+
# tagline:: The subheading for this entry.
|
31
|
+
# tags:: A list of free-tagged categories.
|
32
|
+
# author:: The author's username.
|
33
|
+
# contributors:: An Array of contributors' usernames.
|
34
|
+
# modified:: A modification time.
|
35
|
+
# created:: The time the Entry was initially created.
|
36
|
+
# summary:: A brief description of this entry. Can be used
|
37
|
+
# for an abbreviated text of a long article.
|
38
|
+
# content:: The full text of the entry.
|
39
|
+
#
|
40
|
+
# The following read-only properties are also available:
|
41
|
+
#
|
42
|
+
# day_id:: The day ID can act as a path where other
|
43
|
+
# entry, posted on the same day, are stored.
|
44
|
+
# month_id:: A path for the month's entries.
|
45
|
+
# year_id:: A path for the year's entries.
|
46
|
+
class Entry < BaseEntry
|
47
|
+
|
48
|
+
_ :title, :req => true, :edit_as => :text, :search => :fulltext
|
49
|
+
_ :tagline, :edit_as => :text, :search => :fulltext, :text_processor => true
|
50
|
+
_ :summary, :edit_as => :textarea, :search => :fulltext, :text_processor => true
|
51
|
+
_ :content, :req => true, :edit_as => :textarea, :search => :fulltext, :text_processor => true
|
52
|
+
|
53
|
+
# Hobix::Entry objects are typed in YAML as !hobix.com,2004/entry
|
54
|
+
# objects. This type is virtually identical to !okay/news/feed objects,
|
55
|
+
# which are documented at http://yaml.kwiki.org/?OkayNews.
|
56
|
+
yaml_type "tag:okay.yaml.org,2002:news/entry#1.0"
|
57
|
+
yaml_type "tag:hobix.com,2004:entry"
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
module Hobix
|
63
|
+
# The EntryEnum class is mixed into an Array of entries just before
|
64
|
+
# passing on to a template. This Enumerator-like module provides some
|
65
|
+
# common iteration of entries.
|
66
|
+
module EntryEnum
|
67
|
+
# Calls the block with two arguments: (1) a Time object with
|
68
|
+
# the earliest date of an issued post for that day; (2) an
|
69
|
+
# Array of entries posted that day, in chronological order.
|
70
|
+
def each_day
|
71
|
+
last_day, day = nil, []
|
72
|
+
each do |e|
|
73
|
+
if last_day and last_day != e.day_id
|
74
|
+
yield day.first.created, day
|
75
|
+
day = []
|
76
|
+
end
|
77
|
+
last_day = e.day_id
|
78
|
+
day << e
|
79
|
+
end
|
80
|
+
yield day.first.created, day if last_day
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
#
|
2
|
+
# = hobix/facets/comments.rb
|
3
|
+
#
|
4
|
+
# Hobix command-line weblog system, API for comments.
|
5
|
+
#
|
6
|
+
# Copyright (c) 2003-2004 why the lucky stiff
|
7
|
+
#
|
8
|
+
# Written & maintained by why the lucky stiff <why@ruby-lang.org>
|
9
|
+
#
|
10
|
+
# This program is free software, released under a BSD license.
|
11
|
+
# See COPYING for details.
|
12
|
+
#
|
13
|
+
#--
|
14
|
+
# $Id$
|
15
|
+
#++
|
16
|
+
|
17
|
+
require 'hobix/entry'
|
18
|
+
|
19
|
+
module Hobix
|
20
|
+
module Facets
|
21
|
+
|
22
|
+
# The Comments plugin adds a remote API for adding comments.
|
23
|
+
# Basically, to add comments to your site, ensure the plugin
|
24
|
+
# is loaded within your hobix.yaml `requires' list:
|
25
|
+
#
|
26
|
+
# requires:
|
27
|
+
# - hobix/facets/comments
|
28
|
+
#
|
29
|
+
class Comments < BaseFacet
|
30
|
+
def self.form_field( name ); "hobix_comment:#{ name }" end
|
31
|
+
def self.comment_fields; ['author', 'content']; end
|
32
|
+
def self.comment_class; Hobix::Comment end
|
33
|
+
|
34
|
+
def initialize( weblog, defaults = {} )
|
35
|
+
@weblog = weblog
|
36
|
+
end
|
37
|
+
def get app
|
38
|
+
if app.respond_to? :action_uri
|
39
|
+
action, entry_id = app.action_uri.split( '/', 2 )
|
40
|
+
case action
|
41
|
+
when "comment"
|
42
|
+
# Create the comment entry
|
43
|
+
on_entry = @weblog.storage.load_entry( entry_id )
|
44
|
+
comment = Comments.comment_class.new do |c|
|
45
|
+
Comments.comment_fields.each do |cf|
|
46
|
+
getf = Comments.form_field cf
|
47
|
+
if app._POST[getf].to_s.empty?
|
48
|
+
app.puts "Missing field `#{ getf }'. Please back up and try again."
|
49
|
+
return true
|
50
|
+
end
|
51
|
+
c.method( "#{ cf }=" ).call( app._POST[getf] )
|
52
|
+
end
|
53
|
+
c.created = Time.now
|
54
|
+
c.ipaddress = app.remote_addr
|
55
|
+
end
|
56
|
+
|
57
|
+
# Save the comment, upgen
|
58
|
+
@weblog.storage.append_to_attachment( entry_id, 'comments', comment )
|
59
|
+
@weblog.regenerate :update
|
60
|
+
|
61
|
+
# Redirect
|
62
|
+
link = @weblog.output_entry_map[entry_id]
|
63
|
+
app.setup_redirection( 302, link[:page].link )
|
64
|
+
return true
|
65
|
+
when "preview"
|
66
|
+
app.puts RedCloth.new( app._POST[Comments.form_field('content')] ).to_html
|
67
|
+
return true
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|