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.
Files changed (48) hide show
  1. checksums.yaml +7 -0
  2. data/bin/hobix +90 -0
  3. data/lib/hobix/api.rb +91 -0
  4. data/lib/hobix/article.rb +22 -0
  5. data/lib/hobix/base.rb +477 -0
  6. data/lib/hobix/bixwik.rb +200 -0
  7. data/lib/hobix/commandline.rb +661 -0
  8. data/lib/hobix/comments.rb +99 -0
  9. data/lib/hobix/config.rb +39 -0
  10. data/lib/hobix/datamarsh.rb +110 -0
  11. data/lib/hobix/entry.rb +83 -0
  12. data/lib/hobix/facets/comments.rb +74 -0
  13. data/lib/hobix/facets/publisher.rb +314 -0
  14. data/lib/hobix/facets/trackbacks.rb +80 -0
  15. data/lib/hobix/linklist.rb +76 -0
  16. data/lib/hobix/out/atom.rb +92 -0
  17. data/lib/hobix/out/erb.rb +64 -0
  18. data/lib/hobix/out/okaynews.rb +55 -0
  19. data/lib/hobix/out/quick.rb +312 -0
  20. data/lib/hobix/out/rdf.rb +97 -0
  21. data/lib/hobix/out/redrum.rb +26 -0
  22. data/lib/hobix/out/rss.rb +115 -0
  23. data/lib/hobix/plugin/bloglines.rb +73 -0
  24. data/lib/hobix/plugin/calendar.rb +220 -0
  25. data/lib/hobix/plugin/flickr.rb +110 -0
  26. data/lib/hobix/plugin/recent_comments.rb +82 -0
  27. data/lib/hobix/plugin/sections.rb +91 -0
  28. data/lib/hobix/plugin/tags.rb +60 -0
  29. data/lib/hobix/publish/ping.rb +53 -0
  30. data/lib/hobix/publish/replicate.rb +283 -0
  31. data/lib/hobix/publisher.rb +18 -0
  32. data/lib/hobix/search/dictionary.rb +141 -0
  33. data/lib/hobix/search/porter_stemmer.rb +203 -0
  34. data/lib/hobix/search/simple.rb +209 -0
  35. data/lib/hobix/search/vector.rb +100 -0
  36. data/lib/hobix/storage/filesys.rb +398 -0
  37. data/lib/hobix/trackbacks.rb +94 -0
  38. data/lib/hobix/util/objedit.rb +193 -0
  39. data/lib/hobix/util/patcher.rb +155 -0
  40. data/lib/hobix/webapp/cli.rb +195 -0
  41. data/lib/hobix/webapp/htmlform.rb +107 -0
  42. data/lib/hobix/webapp/message.rb +177 -0
  43. data/lib/hobix/webapp/urigen.rb +141 -0
  44. data/lib/hobix/webapp/webrick-servlet.rb +90 -0
  45. data/lib/hobix/webapp.rb +723 -0
  46. data/lib/hobix/weblog.rb +860 -0
  47. data/lib/hobix.rb +223 -0
  48. 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="&gt;&gt;" />
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
@@ -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
@@ -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