hobix 0.4 → 0.6
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.
- data/COPYING +18 -0
- data/README +18 -0
- data/Rakefile +96 -0
- data/bin/hobix +7 -3
- data/contrib/blosxom-to-hobix.rb +253 -0
- data/contrib/txp-to-hobix.rb +56 -0
- data/contrib/webrick-all-mine.rb +20 -0
- data/doc/CHANGELOG +285 -0
- data/doc/rdoc/classes/Hobix/API.html +382 -0
- data/doc/rdoc/classes/Hobix/Article.html +111 -0
- data/doc/rdoc/classes/Hobix/BaseContent.html +692 -0
- data/doc/rdoc/classes/Hobix/BaseEntry.html +218 -0
- data/doc/rdoc/classes/Hobix/BaseFacet.html +205 -0
- data/doc/rdoc/classes/Hobix/BaseOutput.html +122 -0
- data/doc/rdoc/classes/Hobix/BasePlugin.html +201 -0
- data/doc/rdoc/classes/Hobix/BaseProperties/ClassMethods.html +243 -0
- data/doc/rdoc/classes/Hobix/BaseProperties.html +218 -0
- data/doc/rdoc/classes/Hobix/BasePublish.html +157 -0
- data/doc/rdoc/classes/Hobix/BaseStorage.html +417 -0
- data/doc/rdoc/classes/Hobix/BixWik/Entry.html +196 -0
- data/doc/rdoc/classes/Hobix/BixWik/IndexEntry.html +170 -0
- data/doc/rdoc/classes/Hobix/BixWik/WikiRedCloth.html +111 -0
- data/doc/rdoc/classes/Hobix/BixWik.html +418 -0
- data/doc/rdoc/classes/Hobix/BixWikPlugin.html +158 -0
- data/doc/rdoc/classes/Hobix/CommandLine.html +1970 -0
- data/doc/rdoc/classes/Hobix/Comment.html +113 -0
- data/doc/rdoc/classes/Hobix/Config.html +212 -0
- data/doc/rdoc/classes/Hobix/DataMarsh.html +667 -0
- data/doc/rdoc/classes/Hobix/Entry.html +178 -0
- data/doc/rdoc/classes/Hobix/EntryEnum.html +162 -0
- data/doc/rdoc/classes/Hobix/Enumerable.html +170 -0
- data/doc/rdoc/classes/Hobix/Facets/WikiEdit.html +180 -0
- data/doc/rdoc/classes/Hobix/Facets.html +111 -0
- data/doc/rdoc/classes/Hobix/LinkList.html +182 -0
- data/doc/rdoc/classes/Hobix/Out/Quick.html +412 -0
- data/doc/rdoc/classes/Hobix/Out.html +119 -0
- data/doc/rdoc/classes/Hobix/Page.html +381 -0
- data/doc/rdoc/classes/Hobix/Trackback.html +113 -0
- data/doc/rdoc/classes/Hobix/UriStr.html +198 -0
- data/doc/rdoc/classes/Hobix/WebApp/QueryString.html +207 -0
- data/doc/rdoc/classes/Hobix/WebApp/QueryValidationFailure.html +111 -0
- data/doc/rdoc/classes/Hobix/WebApp.html +1383 -0
- data/doc/rdoc/classes/Hobix/Weblog/AuthorNotFound.html +111 -0
- data/doc/rdoc/classes/Hobix/Weblog.html +2082 -0
- data/doc/rdoc/classes/Hobix.html +399 -0
- data/doc/rdoc/classes/Kernel.html +139 -0
- data/doc/rdoc/classes/Regexp.html +154 -0
- data/doc/rdoc/classes/YAML/Omap.html +144 -0
- data/doc/rdoc/classes/YAML.html +111 -0
- data/doc/rdoc/created.rid +1 -0
- data/doc/rdoc/files/COPYING.html +129 -0
- data/doc/rdoc/files/README.html +131 -0
- data/doc/rdoc/files/doc/CHANGELOG.html +101 -0
- data/doc/rdoc/files/lib/hobix/api_rb.html +119 -0
- data/doc/rdoc/files/lib/hobix/article_rb.html +126 -0
- data/doc/rdoc/files/lib/hobix/base_rb.html +128 -0
- data/doc/rdoc/files/lib/hobix/bixwik_rb.html +126 -0
- data/doc/rdoc/files/lib/hobix/commandline_rb.html +140 -0
- data/doc/rdoc/files/lib/hobix/comments_rb.html +126 -0
- data/doc/rdoc/files/lib/hobix/config_rb.html +125 -0
- data/doc/rdoc/files/lib/hobix/datamarsh_rb.html +108 -0
- data/doc/rdoc/files/lib/hobix/entry_rb.html +118 -0
- data/doc/rdoc/files/lib/hobix/linklist_rb.html +127 -0
- data/doc/rdoc/files/lib/hobix/publisher_rb.html +126 -0
- data/doc/rdoc/files/lib/hobix/trackbacks_rb.html +128 -0
- data/doc/rdoc/files/lib/hobix/webapp_rb.html +127 -0
- data/doc/rdoc/files/lib/hobix/weblog_rb.html +135 -0
- data/doc/rdoc/files/lib/hobix_rb.html +127 -0
- data/doc/rdoc/fr_class_index.html +67 -0
- data/doc/rdoc/fr_file_index.html +44 -0
- data/doc/rdoc/fr_method_index.html +307 -0
- data/doc/rdoc/index.html +24 -0
- data/doc/rdoc/rdoc-style.css +208 -0
- data/git_hobix_update.php +13 -0
- data/lib/hobix/base.rb +6 -3
- data/lib/hobix/bixwik.rb +12 -12
- data/lib/hobix/commandline.rb +18 -2
- data/lib/hobix/comments.rb +4 -5
- data/lib/hobix/entry.rb +2 -1
- data/lib/hobix/facets/comments.rb +31 -6
- data/lib/hobix/linklist.rb +6 -1
- data/lib/hobix/out/atom.rb +29 -20
- data/lib/hobix/out/quick.rb +8 -6
- data/lib/hobix/out/rss.rb +16 -3
- data/lib/hobix/plugin/akismet.rb +196 -0
- data/lib/hobix/plugin/calendar.rb +6 -14
- data/lib/hobix/plugin/recent_comments.rb +4 -2
- data/lib/hobix/plugin/tags.rb +1 -1
- data/lib/hobix/storage/filesys.rb +41 -31
- data/lib/hobix/trackbacks.rb +1 -2
- data/lib/hobix/weblog.rb +73 -40
- data/lib/hobix.rb +9 -2
- data/share/default-blog/hobix.yaml +16 -0
- data/share/default-blog/htdocs/site.css +174 -0
- data/share/default-blog/skel/entry.html.quick +0 -0
- data/share/default-blog/skel/index.atom.atom +0 -0
- data/share/default-blog/skel/index.html.quick-summary +0 -0
- data/share/default-blog/skel/index.xml.rss +0 -0
- data/share/default-blog/skel/index.yaml.okaynews +0 -0
- data/share/default-blog/skel/monthly.html.quick-archive +0 -0
- data/share/default-blog/skel/section.html.quick-archive +0 -0
- data/share/default-blog/skel/yearly.html.quick-archive +0 -0
- data/share/default-blog-modes.yaml +7 -0
- data/share/default-blog.apache-cgi.patch +8 -0
- data/share/default-blog.apache-ssi.patch +38 -0
- data/share/default-blog.apache2-ssi.patch +3 -0
- data/share/default-blog.cgi.patch +8 -0
- data/share/default-blog.comments.patch +5 -0
- data/share/default-blog.prototype.patch +766 -0
- data/share/default-blog.publisher.patch +5 -0
- data/share/default-blog.wiki.patch +29 -0
- data/share/publisher/css/control.css +90 -0
- data/share/publisher/css/form.css +238 -0
- data/share/publisher/css/form.import.css +72 -0
- data/share/publisher/css/main-menu.css +134 -0
- data/share/publisher/i/hobix-emblazen-1.png +0 -0
- data/share/publisher/i/hobix-emblazen-2.png +0 -0
- data/share/publisher/i/hobix-emblazen-3.png +0 -0
- data/share/publisher/i/hobix-emblazen-4.png +0 -0
- data/share/publisher/i/hobix-emblazen-5.png +0 -0
- data/share/publisher/i/hobix-emblazen-6.png +0 -0
- data/share/publisher/i/hobix-emblazen-7.png +0 -0
- data/share/publisher/index.erb +66 -0
- data/share/publisher/js/controls.js +261 -0
- data/share/publisher/js/dragdrop.js +476 -0
- data/share/publisher/js/effects.js +570 -0
- data/share/publisher/js/prototype.js +1011 -0
- metadata +196 -53
- checksums.yaml +0 -7
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
|
|
2
|
+
body {
|
|
3
|
+
font-family: Verdana,Arial,Helvetica,sans-serif;
|
|
4
|
+
font-size: 90%;
|
|
5
|
+
margin: 0;
|
|
6
|
+
margin-left: 40px;
|
|
7
|
+
padding: 0;
|
|
8
|
+
background: white;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
h1,h2,h3,h4 { margin: 0; color: #efefef; background: transparent; }
|
|
12
|
+
h1 { font-size: 150%; }
|
|
13
|
+
h2,h3,h4 { margin-top: 1em; }
|
|
14
|
+
|
|
15
|
+
a { background: #eef; color: #039; text-decoration: none; }
|
|
16
|
+
a:hover { background: #039; color: #eef; }
|
|
17
|
+
|
|
18
|
+
/* Override the base stylesheet's Anchor inside a table cell */
|
|
19
|
+
td > a {
|
|
20
|
+
background: transparent;
|
|
21
|
+
color: #039;
|
|
22
|
+
text-decoration: none;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/* and inside a section title */
|
|
26
|
+
.section-title > a {
|
|
27
|
+
background: transparent;
|
|
28
|
+
color: #eee;
|
|
29
|
+
text-decoration: none;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/* === Structural elements =================================== */
|
|
33
|
+
|
|
34
|
+
div#index {
|
|
35
|
+
margin: 0;
|
|
36
|
+
margin-left: -40px;
|
|
37
|
+
padding: 0;
|
|
38
|
+
font-size: 90%;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
div#index a {
|
|
43
|
+
margin-left: 0.7em;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
div#index .section-bar {
|
|
47
|
+
margin-left: 0px;
|
|
48
|
+
padding-left: 0.7em;
|
|
49
|
+
background: #ccc;
|
|
50
|
+
font-size: small;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
div#classHeader, div#fileHeader {
|
|
55
|
+
width: auto;
|
|
56
|
+
color: white;
|
|
57
|
+
padding: 0.5em 1.5em 0.5em 1.5em;
|
|
58
|
+
margin: 0;
|
|
59
|
+
margin-left: -40px;
|
|
60
|
+
border-bottom: 3px solid #006;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
div#classHeader a, div#fileHeader a {
|
|
64
|
+
background: inherit;
|
|
65
|
+
color: white;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
div#classHeader td, div#fileHeader td {
|
|
69
|
+
background: inherit;
|
|
70
|
+
color: white;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
div#fileHeader {
|
|
75
|
+
background: #057;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
div#classHeader {
|
|
79
|
+
background: #048;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
.class-name-in-header {
|
|
84
|
+
font-size: 180%;
|
|
85
|
+
font-weight: bold;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
div#bodyContent {
|
|
90
|
+
padding: 0 1.5em 0 1.5em;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
div#description {
|
|
94
|
+
padding: 0.5em 1.5em;
|
|
95
|
+
background: #efefef;
|
|
96
|
+
border: 1px dotted #999;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
div#description h1,h2,h3,h4,h5,h6 {
|
|
100
|
+
color: #125;;
|
|
101
|
+
background: transparent;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
div#validator-badges {
|
|
105
|
+
text-align: center;
|
|
106
|
+
}
|
|
107
|
+
div#validator-badges img { border: 0; }
|
|
108
|
+
|
|
109
|
+
div#copyright {
|
|
110
|
+
color: #333;
|
|
111
|
+
background: #efefef;
|
|
112
|
+
font: 0.75em sans-serif;
|
|
113
|
+
margin-top: 5em;
|
|
114
|
+
margin-bottom: 0;
|
|
115
|
+
padding: 0.5em 2em;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
/* === Classes =================================== */
|
|
120
|
+
|
|
121
|
+
table.header-table {
|
|
122
|
+
color: white;
|
|
123
|
+
font-size: small;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.type-note {
|
|
127
|
+
font-size: small;
|
|
128
|
+
color: #DEDEDE;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.xxsection-bar {
|
|
132
|
+
background: #eee;
|
|
133
|
+
color: #333;
|
|
134
|
+
padding: 3px;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.section-bar {
|
|
138
|
+
color: #333;
|
|
139
|
+
border-bottom: 1px solid #999;
|
|
140
|
+
margin-left: -20px;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
.section-title {
|
|
145
|
+
background: #79a;
|
|
146
|
+
color: #eee;
|
|
147
|
+
padding: 3px;
|
|
148
|
+
margin-top: 2em;
|
|
149
|
+
margin-left: -30px;
|
|
150
|
+
border: 1px solid #999;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.top-aligned-row { vertical-align: top }
|
|
154
|
+
.bottom-aligned-row { vertical-align: bottom }
|
|
155
|
+
|
|
156
|
+
/* --- Context section classes ----------------------- */
|
|
157
|
+
|
|
158
|
+
.context-row { }
|
|
159
|
+
.context-item-name { font-family: monospace; font-weight: bold; color: black; }
|
|
160
|
+
.context-item-value { font-size: small; color: #448; }
|
|
161
|
+
.context-item-desc { color: #333; padding-left: 2em; }
|
|
162
|
+
|
|
163
|
+
/* --- Method classes -------------------------- */
|
|
164
|
+
.method-detail {
|
|
165
|
+
background: #efefef;
|
|
166
|
+
padding: 0;
|
|
167
|
+
margin-top: 0.5em;
|
|
168
|
+
margin-bottom: 1em;
|
|
169
|
+
border: 1px dotted #ccc;
|
|
170
|
+
}
|
|
171
|
+
.method-heading {
|
|
172
|
+
color: black;
|
|
173
|
+
background: #ccc;
|
|
174
|
+
border-bottom: 1px solid #666;
|
|
175
|
+
padding: 0.2em 0.5em 0 0.5em;
|
|
176
|
+
}
|
|
177
|
+
.method-signature { color: black; background: inherit; }
|
|
178
|
+
.method-name { font-weight: bold; }
|
|
179
|
+
.method-args { font-style: italic; }
|
|
180
|
+
.method-description { padding: 0 0.5em 0 0.5em; }
|
|
181
|
+
|
|
182
|
+
/* --- Source code sections -------------------- */
|
|
183
|
+
|
|
184
|
+
a.source-toggle { font-size: 90%; }
|
|
185
|
+
div.method-source-code {
|
|
186
|
+
background: #262626;
|
|
187
|
+
color: #ffdead;
|
|
188
|
+
margin: 1em;
|
|
189
|
+
padding: 0.5em;
|
|
190
|
+
border: 1px dashed #999;
|
|
191
|
+
overflow: hidden;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
div.method-source-code pre { color: #ffdead; overflow: hidden; }
|
|
195
|
+
|
|
196
|
+
/* --- Ruby keyword styles --------------------- */
|
|
197
|
+
|
|
198
|
+
.standalone-code { background: #221111; color: #ffdead; overflow: hidden; }
|
|
199
|
+
|
|
200
|
+
.ruby-constant { color: #7fffd4; background: transparent; }
|
|
201
|
+
.ruby-keyword { color: #00ffff; background: transparent; }
|
|
202
|
+
.ruby-ivar { color: #eedd82; background: transparent; }
|
|
203
|
+
.ruby-operator { color: #00ffee; background: transparent; }
|
|
204
|
+
.ruby-identifier { color: #ffdead; background: transparent; }
|
|
205
|
+
.ruby-node { color: #ffa07a; background: transparent; }
|
|
206
|
+
.ruby-comment { color: #b22222; font-weight: bold; background: transparent; }
|
|
207
|
+
.ruby-regexp { color: #ffa07a; background: transparent; }
|
|
208
|
+
.ruby-value { color: #7fffd4; background: transparent; }
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
/**
|
|
3
|
+
* This file should be placed in the htdocs of your actual blog repo
|
|
4
|
+
*/
|
|
5
|
+
if($_POST["payload"]) {
|
|
6
|
+
#run git pull
|
|
7
|
+
system("git pull origin master:master");
|
|
8
|
+
echo "Thank you, come again!";
|
|
9
|
+
} else {
|
|
10
|
+
echo "Sorry, you don't come bearing gifts.\n\n";
|
|
11
|
+
}
|
|
12
|
+
?>
|
|
13
|
+
|
data/lib/hobix/base.rb
CHANGED
|
@@ -94,6 +94,7 @@ class BaseStorage < BasePlugin
|
|
|
94
94
|
e.link = e.class.url_link e, @link, "html"
|
|
95
95
|
e.created = Time.now
|
|
96
96
|
e.modified = Time.now
|
|
97
|
+
e.updated = Time.now
|
|
97
98
|
e.title = "This Ghostly Message From the Slime Will Soon Vanish!"
|
|
98
99
|
e.tagline = "A temporary message, a tingling sensation, Hobix is up!!"
|
|
99
100
|
e.author = author
|
|
@@ -304,7 +305,8 @@ class BaseContent
|
|
|
304
305
|
_ :link
|
|
305
306
|
_ :title, :edit_as => :text, :search => :fulltext
|
|
306
307
|
_ :created, :edit_as => :datetime, :search => :prefix
|
|
307
|
-
_ :modified
|
|
308
|
+
_ :modified, :show_as => :datetime
|
|
309
|
+
_ :updated, :show_as => :datetime
|
|
308
310
|
_ :tags, :edit_as => :text, :search => :prefix
|
|
309
311
|
|
|
310
312
|
def initialize; yield self if block_given?; end
|
|
@@ -395,7 +397,7 @@ class BaseContent
|
|
|
395
397
|
instance_eval %{
|
|
396
398
|
def @#{ f }.to_yaml( opts = {} )
|
|
397
399
|
s = self.to_str
|
|
398
|
-
def s.to_yaml_style; :
|
|
400
|
+
def s.to_yaml_style; :literal; end
|
|
399
401
|
s.to_yaml( opts )
|
|
400
402
|
end
|
|
401
403
|
}
|
|
@@ -446,7 +448,8 @@ class BaseEntry < BaseContent
|
|
|
446
448
|
_ :author, :req => true, :edit_as => :text, :search => :prefix
|
|
447
449
|
_ :contributors, :edit_as => :array, :search => :prefix
|
|
448
450
|
_ :created, :edit_as => :datetime, :search => :prefix
|
|
449
|
-
_ :modified
|
|
451
|
+
_ :modified, :show_as => :datetime
|
|
452
|
+
_ :updated, :show_as => :datetime
|
|
450
453
|
_ :tags, :edit_as => :text, :search => :prefix
|
|
451
454
|
_ :content, :edit_as => :textarea, :search => :fulltext, :text_processor => true
|
|
452
455
|
_ :content_ratings, :edit_as => :array
|
data/lib/hobix/bixwik.rb
CHANGED
|
@@ -42,9 +42,9 @@ module BixWik
|
|
|
42
42
|
|
|
43
43
|
# Handler for templates with `index' prefix. These pages simply
|
|
44
44
|
# mirror the `HomePage' entry.
|
|
45
|
-
def skel_index( path_storage )
|
|
45
|
+
def skel_index( path_storage, section_path )
|
|
46
46
|
homePage = path_storage.match( /^HomePage$/ ).first
|
|
47
|
-
page = Page.new( '
|
|
47
|
+
page = Page.new( 'index' )
|
|
48
48
|
unless homePage
|
|
49
49
|
homePage = Hobix::Storage::IndexEntry.new( path_storage.default_entry( authors.keys.first ) )
|
|
50
50
|
end
|
|
@@ -56,32 +56,32 @@ module BixWik
|
|
|
56
56
|
# Handler for templates with `list/index' prefix. These templates will
|
|
57
57
|
# receive IndexEntry objects for every entry in the system. Only one
|
|
58
58
|
# index page is requested by this handler.
|
|
59
|
-
def skel_recent_index( path_storage )
|
|
59
|
+
def skel_recent_index( path_storage, section_path )
|
|
60
60
|
index_entries = storage.find( :all => true )
|
|
61
|
-
page = Page.new( '
|
|
61
|
+
page = Page.new( 'list/index' )
|
|
62
62
|
page.timestamp = index_entries.first.created
|
|
63
|
-
page.updated = storage.
|
|
63
|
+
page.updated = storage.last_updated( index_entries )
|
|
64
64
|
yield :page => page, :entries => index_entries
|
|
65
65
|
end
|
|
66
66
|
|
|
67
67
|
# Handler for templates with `recent/index' prefix. These templates will
|
|
68
68
|
# receive entries loaded by +Hobix::BaseStorage#lastn+. Only one
|
|
69
69
|
# index page is requested by this handler.
|
|
70
|
-
def skel_recent_index( path_storage )
|
|
70
|
+
def skel_recent_index( path_storage, section_path )
|
|
71
71
|
index_entries = storage.lastn( @lastn || 120 )
|
|
72
|
-
page = Page.new( '
|
|
72
|
+
page = Page.new( 'recent/index' )
|
|
73
73
|
page.timestamp = index_entries.first.created
|
|
74
|
-
page.updated = storage.
|
|
74
|
+
page.updated = storage.last_updated( index_entries )
|
|
75
75
|
yield :page => page, :entries => index_entries
|
|
76
76
|
end
|
|
77
77
|
|
|
78
78
|
# Handler for templates with `list/index' prefix. These templates will
|
|
79
79
|
# receive a list of all pages in the Wiki.
|
|
80
|
-
def skel_list_index( path_storage )
|
|
80
|
+
def skel_list_index( path_storage, section_path )
|
|
81
81
|
all_pages = storage.all
|
|
82
|
-
page = Page.new( '
|
|
82
|
+
page = Page.new( 'list/index' )
|
|
83
83
|
page.timestamp = all_pages.first.created
|
|
84
|
-
page.updated = storage.
|
|
84
|
+
page.updated = storage.last_updated( all_pages )
|
|
85
85
|
yield :page => page, :entries => all_pages, :no_load => true
|
|
86
86
|
end
|
|
87
87
|
|
|
@@ -193,7 +193,7 @@ def entry_content_erb
|
|
|
193
193
|
end
|
|
194
194
|
def sidebar_erb; nil; end
|
|
195
195
|
def entry_footer_erb; %{
|
|
196
|
-
Revision from <%= ( entry.modified || entry.created ).strftime( "%
|
|
196
|
+
Revision from <%= ( entry.modified || entry.created ).strftime( "%d %B %Y at %H:%M" ) %> by <%= weblog.wiki_link( "authors/" + entry.author ) %> }
|
|
197
197
|
end
|
|
198
198
|
end
|
|
199
199
|
end
|
data/lib/hobix/commandline.rb
CHANGED
|
@@ -109,13 +109,25 @@ module CommandLine
|
|
|
109
109
|
require 'open-uri'
|
|
110
110
|
c = ::Config::CONFIG.merge( config )
|
|
111
111
|
eval(open("http://go.hobix.com/").read)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
# Now look at all blogs and delete entries/index.{hobix,search}
|
|
115
|
+
if @config['weblogs'].respond_to? :sort
|
|
116
|
+
blogs = @config['weblogs'].sort
|
|
117
|
+
blogs.each do |e|
|
|
118
|
+
weblog = Hobix::Weblog.load( e[1] )
|
|
119
|
+
puts "Removing index.search and index.hobix from #{weblog.entry_path}"
|
|
120
|
+
File.safe_unlink( File.join(weblog.entry_path, "index.search"),
|
|
121
|
+
File.join(weblog.entry_path, "index.hobix"))
|
|
122
|
+
end
|
|
123
|
+
end
|
|
112
124
|
end
|
|
113
125
|
|
|
114
126
|
# List all your weblogs
|
|
115
127
|
def blogs_weblog_explain; "List your weblogs."; end
|
|
116
128
|
def blogs_weblog_args; []; end
|
|
117
129
|
def blogs_weblog
|
|
118
|
-
if @config['weblogs'].respond_to? :sort
|
|
130
|
+
if @config['weblogs'].respond_to?( :sort ) && !@config['weblogs'].empty?
|
|
119
131
|
blogs = @config['weblogs'].sort
|
|
120
132
|
name_width = blogs.collect { |b| b[0].length }.max
|
|
121
133
|
tabular( blogs, [[-name_width, 0, 'weblog-name'], [-40, 1, 'path']] )
|
|
@@ -433,6 +445,8 @@ module CommandLine
|
|
|
433
445
|
else
|
|
434
446
|
@config['post upgen'] = true
|
|
435
447
|
end
|
|
448
|
+
|
|
449
|
+
|
|
436
450
|
save_config
|
|
437
451
|
end
|
|
438
452
|
|
|
@@ -463,8 +477,8 @@ module CommandLine
|
|
|
463
477
|
puts "If you want to join an existing hobix weblog, we can do that now."
|
|
464
478
|
puts "Each weblog needs a name and a path. Use <ENTER> at any prompt"
|
|
465
479
|
puts "to simply move on."
|
|
480
|
+
puts
|
|
466
481
|
loop do
|
|
467
|
-
puts
|
|
468
482
|
puts "Short name for weblog, used on the command line (i.e. hobix upgen blogName)."
|
|
469
483
|
print ": "
|
|
470
484
|
blogname = gets.strip
|
|
@@ -477,6 +491,8 @@ module CommandLine
|
|
|
477
491
|
break
|
|
478
492
|
end
|
|
479
493
|
add_weblog( blogname, blogpath )
|
|
494
|
+
puts
|
|
495
|
+
puts "** Add another weblog?"
|
|
480
496
|
end
|
|
481
497
|
|
|
482
498
|
puts "To setup more weblogs later, use: hobix add #{ add_weblog_args.join( ' ' ) }"
|
data/lib/hobix/comments.rb
CHANGED
|
@@ -45,14 +45,13 @@ append_def :entry_erb, %{
|
|
|
45
45
|
|
|
46
46
|
def entry_comment_erb; %{
|
|
47
47
|
<% entry_id = entry.id %>
|
|
48
|
-
<a name="comments"></a>
|
|
49
48
|
<div id="comments">
|
|
50
49
|
<% comments = weblog.storage.load_attached( entry_id, "comments" ) rescue [] %>
|
|
51
50
|
<% comments.each do |comment| %>
|
|
52
51
|
<div class="entry">
|
|
53
52
|
<div class="entryAttrib">
|
|
54
53
|
<div class="entryAuthor"><h3><%= comment.author %></h3></div>
|
|
55
|
-
<div class="entryTime">said on <%= comment.created.strftime( "<nobr>%d %b %Y</nobr> at <nobr>%
|
|
54
|
+
<div class="entryTime">said on <%= comment.created.strftime( "<nobr>%d %b %Y</nobr> at <nobr>%H:%M</nobr>" ) %></div>
|
|
56
55
|
</div>
|
|
57
56
|
<div class="entryContentOuter"><div class="entryContent"><%= comment.content.to_html %></div></div>
|
|
58
57
|
</div>
|
|
@@ -61,15 +60,15 @@ def entry_comment_erb; %{
|
|
|
61
60
|
|
|
62
61
|
def entry_comment_form_erb; %{
|
|
63
62
|
<div class="entry">
|
|
64
|
-
<form id="userComment" method="post" action="/control/comment
|
|
63
|
+
<form id="userComment" method="post" action="<%= weblog.expand_path( '/control/comment/' + entry_id )%>">
|
|
65
64
|
<div class="entryAttrib">
|
|
66
65
|
<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
|
|
66
|
+
<div id="liveTime" class="entryTime">said on <%= Time.now.strftime( "<nobr>%d %b %Y</nobr> at <nobr>%H:%M</nobr>")%></div>
|
|
68
67
|
</div>
|
|
69
68
|
<div class="entryContentOuter"><div class="entryContent">
|
|
70
69
|
<textarea name="<%= Hobix::Facets::Comments.form_field 'content' %>" rows="6" cols="50"></textarea>
|
|
71
70
|
<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 }})" />
|
|
71
|
+
onClick="new Ajax.Request( '<%= weblog.expand_path '/control/preview' %>', {parameters: Form.serialize('userComment'), onComplete: function(req) { $('textilePreview').innerHTML = req.responseText }})" />
|
|
73
72
|
<input type="submit" name="<%= Hobix::Facets::Comments.form_field 'submit' %>" value=">>" />
|
|
74
73
|
<small>* do <a href="javascript:quickRedReference();">fancy stuff</a> in your comment.</small>
|
|
75
74
|
</p>
|
data/lib/hobix/entry.rb
CHANGED
|
@@ -31,8 +31,9 @@ module Hobix
|
|
|
31
31
|
# tags:: A list of free-tagged categories.
|
|
32
32
|
# author:: The author's username.
|
|
33
33
|
# contributors:: An Array of contributors' usernames.
|
|
34
|
-
# modified:: A modification time.
|
|
35
34
|
# created:: The time the Entry was initially created.
|
|
35
|
+
# modified:: A modification time.
|
|
36
|
+
# updated:: Used internally to ensure an entry has been generated.
|
|
36
37
|
# summary:: A brief description of this entry. Can be used
|
|
37
38
|
# for an abbreviated text of a long article.
|
|
38
39
|
# content:: The full text of the entry.
|
|
@@ -54,13 +54,38 @@ class Comments < BaseFacet
|
|
|
54
54
|
c.ipaddress = app.remote_addr
|
|
55
55
|
end
|
|
56
56
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
57
|
+
# A quick hack to try akismet content spam checking
|
|
58
|
+
if @weblog.requires.detect{ |i| i['hobix/plugin/akismet'] }
|
|
59
|
+
@akismet = Akismet.new(@weblog.link, AkismetKey.key)
|
|
60
|
+
if @akismet.verifyAPIKey
|
|
61
|
+
if @akismet.commentCheck(
|
|
62
|
+
app.remote_addr, # remote IP
|
|
63
|
+
app.get_request_header('User-Agent'), # user agent
|
|
64
|
+
app.get_request_header('Referer'), # http referer
|
|
65
|
+
'', # permalink
|
|
66
|
+
'comment', # comment type
|
|
67
|
+
app._POST['hobix_comment:author'].to_s, # author name
|
|
68
|
+
'', # author email
|
|
69
|
+
'', # author url
|
|
70
|
+
app._POST['hobix_comment:comment'].to_s, # comment text
|
|
71
|
+
{}) # other
|
|
72
|
+
app.puts( "Sorry, that smelled like spam. If wasn't meant to, go back and try again" )
|
|
73
|
+
return true
|
|
74
|
+
end
|
|
75
|
+
else
|
|
76
|
+
# If the key does not verify, post the comment
|
|
77
|
+
# but note the failure in the apache error logs.
|
|
78
|
+
$stderr.puts( "Hobix: Akismet API key did not verify." )
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Save the comment, upgen
|
|
83
|
+
@weblog.storage.append_to_attachment( entry_id, 'comments', comment )
|
|
84
|
+
@weblog.regenerate :update
|
|
85
|
+
|
|
86
|
+
# Redirect
|
|
62
87
|
link = @weblog.output_entry_map[entry_id]
|
|
63
|
-
app.setup_redirection( 302, link[:page].link )
|
|
88
|
+
app.setup_redirection( 302, @weblog.expand_path( link[:page].link ) )
|
|
64
89
|
return true
|
|
65
90
|
when "preview"
|
|
66
91
|
app.puts RedCloth.new( app._POST[Comments.form_field('content')] ).to_html
|
data/lib/hobix/linklist.rb
CHANGED
|
@@ -47,7 +47,7 @@ require 'yaml'
|
|
|
47
47
|
module Hobix
|
|
48
48
|
class LinkList < BaseEntry
|
|
49
49
|
|
|
50
|
-
_ :links,
|
|
50
|
+
_ :links, :req => true, :edit_as => :textarea
|
|
51
51
|
|
|
52
52
|
# Converts the link list into a RedCloth string for display
|
|
53
53
|
# in templates.
|
|
@@ -59,6 +59,11 @@ class LinkList < BaseEntry
|
|
|
59
59
|
)
|
|
60
60
|
end
|
|
61
61
|
|
|
62
|
+
# Adds support for enumeration.
|
|
63
|
+
def each
|
|
64
|
+
@links.each { |title, url| yield title, url }
|
|
65
|
+
end
|
|
66
|
+
|
|
62
67
|
# LinkLists currently output as YAML type family
|
|
63
68
|
# !hobix.com,2004/linklist.
|
|
64
69
|
yaml_type "tag:hobix.com,2004:linklist"
|
data/lib/hobix/out/atom.rb
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
#++
|
|
16
16
|
require 'hobix/base'
|
|
17
17
|
require 'rexml/document'
|
|
18
|
+
require 'erb'
|
|
18
19
|
require 'uri'
|
|
19
20
|
require 'cgi'
|
|
20
21
|
|
|
@@ -23,7 +24,9 @@ module Out
|
|
|
23
24
|
module XmlQuick
|
|
24
25
|
def x( title, txt, attrs = nil )
|
|
25
26
|
e = REXML::Element.new title
|
|
26
|
-
|
|
27
|
+
e.attributes['xml:space'] = "preserve"
|
|
28
|
+
# self-quote to work around REXML quoting issues with HTML entities
|
|
29
|
+
REXML::Text.new ::ERB::Util.h( txt ), true, e, true if txt
|
|
27
30
|
attrs.each { |a,b| e.attributes[a] = b } if attrs
|
|
28
31
|
self << e
|
|
29
32
|
end
|
|
@@ -37,52 +40,58 @@ class Atom < Hobix::BaseOutput
|
|
|
37
40
|
end
|
|
38
41
|
def load( file_name, vars )
|
|
39
42
|
rssdoc = REXML::Document.new( <<EOXML )
|
|
40
|
-
<feed
|
|
41
|
-
xmlns="http://
|
|
43
|
+
<feed
|
|
44
|
+
xmlns="http://www.w3.org/2005/Atom"
|
|
42
45
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
43
46
|
xml:lang="en">
|
|
44
47
|
<title></title>
|
|
45
48
|
<link rel="alternate" type="text/html" href="" />
|
|
46
|
-
<
|
|
47
|
-
<
|
|
49
|
+
<link rel="self" type="application/atom+xml" href="" />
|
|
50
|
+
<updated></updated>
|
|
51
|
+
<subtitle></subtitle>
|
|
48
52
|
<id></id>
|
|
49
|
-
<generator
|
|
50
|
-
<
|
|
53
|
+
<generator uri="http://hobix.com/" version="#{ Hobix::VERSION }">Hobix</generator>
|
|
54
|
+
<rights></rights>
|
|
51
55
|
</feed>
|
|
52
56
|
EOXML
|
|
53
57
|
uri = vars[:weblog].link
|
|
54
58
|
rssdoc << REXML::XMLDecl.new
|
|
55
59
|
rssdoc.elements['/feed/title'].text = vars[:weblog].title
|
|
56
|
-
|
|
57
|
-
rssdoc
|
|
58
|
-
|
|
60
|
+
alt_uri = vars[:weblog].link.to_s
|
|
61
|
+
REXML::XPath.first(rssdoc, '/atom:feed/atom:link[@rel="alternate"]',
|
|
62
|
+
{ 'atom' => 'http://www.w3.org/2005/Atom' }).attributes['href'] = alt_uri
|
|
63
|
+
self_uri = "#{vars[:weblog].link}#{vars[:page].link}"
|
|
64
|
+
REXML::XPath.first(rssdoc, '/atom:feed/atom:link[@rel="self"]',
|
|
65
|
+
{ 'atom' => 'http://www.w3.org/2005/Atom' }).attributes['href'] = self_uri
|
|
66
|
+
rssdoc.elements['/feed'].attributes['xml:base'] = self_uri
|
|
67
|
+
rssdoc.elements['/feed/subtitle'].text = vars[:weblog].tagline
|
|
68
|
+
rssdoc.elements['/feed/updated'].text = vars[:page].updated.strftime( "%Y-%m-%dT%H:%M:%SZ" )
|
|
59
69
|
rssdoc.elements['/feed/id'].text = "tag:#{ uri.host },#{ Time.now.year }:blog#{ uri.path }"
|
|
60
|
-
rssdoc.elements['/feed/
|
|
70
|
+
rssdoc.elements['/feed/rights'].text = vars[:weblog].copyright || "None"
|
|
61
71
|
( vars[:entries] || [vars[:entry]] ).each do |e|
|
|
62
72
|
ele = REXML::Element.new 'entry'
|
|
63
73
|
ele.extend XmlQuick
|
|
74
|
+
ele.attributes['xml:base'] = e.link
|
|
64
75
|
ele.x( 'title', e.title )
|
|
65
76
|
ele.x( 'link', nil, {'rel' => 'alternate', 'type' => 'text/html', 'href' => e.link } )
|
|
66
77
|
ele.x( 'id', "tag:#{ uri.host },#{ Time.now.year }:blog#{ CGI.escape(uri.path) }entry#{ CGI.escape( "/#{ e.id }" ) }" )
|
|
67
|
-
ele.x( '
|
|
68
|
-
ele.x( '
|
|
78
|
+
ele.x( 'published', e.created.strftime( "%Y-%m-%dT%H:%M:%SZ" ) )
|
|
79
|
+
ele.x( 'updated', (e.modified || e.created).strftime( "%Y-%m-%dT%H:%M:%SZ" ) )
|
|
69
80
|
ele.x( 'dc:subject', e.section_id )
|
|
70
|
-
e.tags.each do |t|
|
|
71
|
-
ele.x( '
|
|
81
|
+
e.tags.find_all {|t| not (t.nil? or t == '') }.each do |t|
|
|
82
|
+
ele.x( 'category', '', { 'term' => t, 'scheme' => "http://hobix.com/tags" } )
|
|
72
83
|
end
|
|
73
84
|
ele.x( 'summary',
|
|
74
85
|
e.summary.to_html.gsub( /img src="\//, "img src=\"#{ vars[:weblog].link }/" ),
|
|
75
|
-
{'type' => '
|
|
86
|
+
{'type' => 'html', 'mode' => 'escaped'} ) if e.respond_to? :summary and e.summary and !e.summary.empty?
|
|
76
87
|
author = vars[:weblog].authors[e.author]
|
|
77
88
|
ele_auth = REXML::Element.new 'author'
|
|
78
89
|
ele_auth.extend XmlQuick
|
|
79
90
|
ele_auth.x( 'name', author['name'] )
|
|
80
|
-
ele_auth.x( '
|
|
91
|
+
ele_auth.x( 'uri', author['url'] ) if author['url']
|
|
81
92
|
ele_auth.x( 'email', author['email'] ) if author['email']
|
|
82
93
|
ele << ele_auth
|
|
83
|
-
ele.x( 'content',
|
|
84
|
-
e.content.to_html.gsub( /img src="\//, "img src=\"#{ vars[:weblog].link }/" ),
|
|
85
|
-
{'type' => 'text/html', 'mode' => 'escaped'} )
|
|
94
|
+
ele.x( 'content', e.content.to_html, {'type' => 'html'} )
|
|
86
95
|
rssdoc.elements['/feed'].add ele
|
|
87
96
|
end
|
|
88
97
|
rssdoc.to_s
|
data/lib/hobix/out/quick.rb
CHANGED
|
@@ -189,7 +189,7 @@ class Quick < Hobix::BaseOutput
|
|
|
189
189
|
%{ <div class="sidebarBox">
|
|
190
190
|
<h2 class="sidebarTitle">Syndicate</h2>
|
|
191
191
|
<ul>
|
|
192
|
-
<li><a href="<%= weblog.link %>/index.
|
|
192
|
+
<li><a href="<%= weblog.link %>/index.atom">Atom 1.0</a></li>
|
|
193
193
|
</ul>
|
|
194
194
|
</div> }
|
|
195
195
|
end
|
|
@@ -205,14 +205,15 @@ class Quick < Hobix::BaseOutput
|
|
|
205
205
|
end
|
|
206
206
|
def entries_erb
|
|
207
207
|
%{ <% entries.each_day do |day, day_entries| %>
|
|
208
|
-
<a name="<%= day.strftime( "%Y%m%d" ) %>"></a>
|
|
209
208
|
<+ day_header +>
|
|
210
209
|
<% day_entries.each do |entry| %>
|
|
211
210
|
<+ entry +>
|
|
212
211
|
<% end %>
|
|
213
212
|
<% end %> }
|
|
214
213
|
end
|
|
215
|
-
def day_header_erb;
|
|
214
|
+
def day_header_erb;
|
|
215
|
+
%{ <h2 class="dayHeader" id="<%= day.strftime( "day%Y%m%d" ) %>"><%= day.strftime( "%A, %B %d, %Y" ) %></h2> };
|
|
216
|
+
end
|
|
216
217
|
def entry_erb
|
|
217
218
|
%{ <div class="entry">
|
|
218
219
|
<+ entry_title +>
|
|
@@ -228,7 +229,8 @@ class Quick < Hobix::BaseOutput
|
|
|
228
229
|
%{ <div class="entryContent"><%= entry.content.to_html %></div> }
|
|
229
230
|
end
|
|
230
231
|
def entry_footer_erb
|
|
231
|
-
%{ posted by <%= weblog.authors[entry.author]['name'] %> |
|
|
232
|
+
%{ posted by <%= weblog.authors[entry.author]['name'] %> |
|
|
233
|
+
<a href="<%= weblog.expand_path entry.id %>.html"><%= entry.created.strftime( "%I:%M %p" ) %></a> }
|
|
232
234
|
end
|
|
233
235
|
def head_tags_erb; end
|
|
234
236
|
def css_erb; %{ @import "<%= weblog.expand_path "site.css" %>"; }; end
|
|
@@ -276,7 +278,7 @@ class QuickSummary < Quick
|
|
|
276
278
|
%{ <div class="entryContent">
|
|
277
279
|
<% if entry.respond_to? :summary and entry.summary %>
|
|
278
280
|
<%= entry.summary.to_html %>
|
|
279
|
-
<p><a href="<%= entry.
|
|
281
|
+
<p><a href="<%= weblog.expand_path entry.id %>">Continue to full post.</a></p>
|
|
280
282
|
<% else %>
|
|
281
283
|
<%= entry.content.to_html %>
|
|
282
284
|
<% end %>
|
|
@@ -289,7 +291,7 @@ class QuickArchive < Quick
|
|
|
289
291
|
"quick-archive"
|
|
290
292
|
end
|
|
291
293
|
def entry_erb
|
|
292
|
-
%{ <h3 class="entryTitle"><a href="<%= entry.
|
|
294
|
+
%{ <h3 class="entryTitle"><a href="<%= weblog.expand_path entry.id %>"><%= entry.title %></a></h3> }
|
|
293
295
|
end
|
|
294
296
|
def entries_erb
|
|
295
297
|
%{ <div id="archives">
|