tributary 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. data/.gitignore +1 -0
  2. data/.rspec +6 -0
  3. data/LICENCE +661 -0
  4. data/README.md +99 -0
  5. data/Rakefile +5 -0
  6. data/config.ru +9 -0
  7. data/lib/tributary/app.rb +61 -0
  8. data/lib/tributary/item.rb +66 -0
  9. data/lib/tributary/plugins/dummy.rb +7 -0
  10. data/lib/tributary/plugins/mnml.rb +14 -0
  11. data/lib/tributary/plugins/unbreak_my_art.rb +22 -0
  12. data/lib/tributary/stream.rb +51 -0
  13. data/lib/tributary.rb +8 -0
  14. data/spec/fixtures/index.en.en+pl.xml +50 -0
  15. data/spec/fixtures/index.en.en.xml +50 -0
  16. data/spec/fixtures/index.en.xml +50 -0
  17. data/spec/fixtures/index.pl.pl.xml +50 -0
  18. data/spec/fixtures/index.pl.xml +50 -0
  19. data/spec/fixtures/index.xml +50 -0
  20. data/spec/fixtures/layout.css +22 -0
  21. data/spec/fixtures/pages.css +2 -0
  22. data/spec/site/articles/600.en.md +5 -0
  23. data/spec/site/articles/600.md +5 -0
  24. data/spec/site/articles/bilingual.en.md +4 -0
  25. data/spec/site/articles/bilingual.pl.md +4 -0
  26. data/spec/site/articles/unix-millennium-bug.en.md +4 -0
  27. data/spec/site/articles/welcome.md +4 -0
  28. data/spec/site/beeps/beep.md +3 -0
  29. data/spec/site/beeps/dated.md +3 -0
  30. data/spec/site/beeps/english.en.md +3 -0
  31. data/spec/site/beeps/link.md +3 -0
  32. data/spec/site/beeps/polish.pl.md +3 -0
  33. data/spec/site/beeps/quote.md +4 -0
  34. data/spec/site/i18n/en.yml +12 -0
  35. data/spec/site/i18n/pl.yml +12 -0
  36. data/spec/site/pages/about.md +5 -0
  37. data/spec/site/views/articles.haml +4 -0
  38. data/spec/site/views/articles.index.haml +6 -0
  39. data/spec/site/views/articles.index.sass +0 -0
  40. data/spec/site/views/articles.sass +2 -0
  41. data/spec/site/views/beeps.haml +1 -0
  42. data/spec/site/views/beeps.sass +2 -0
  43. data/spec/site/views/error.haml +8 -0
  44. data/spec/site/views/error.sass +6 -0
  45. data/spec/site/views/index.haml +6 -0
  46. data/spec/site/views/index.sass +2 -0
  47. data/spec/site/views/index.xml.haml +17 -0
  48. data/spec/site/views/layout.haml +56 -0
  49. data/spec/site/views/layout.sass +22 -0
  50. data/spec/site/views/pages.haml +3 -0
  51. data/spec/site/views/pages.sass +2 -0
  52. data/spec/tributary/app_spec.rb +266 -0
  53. data/spec/tributary/item_spec.rb +129 -0
  54. data/spec/tributary/plugins/dummy_spec.rb +12 -0
  55. data/spec/tributary/plugins/mnml_spec.rb +16 -0
  56. data/spec/tributary/plugins/unbreak_my_art_spec.rb +36 -0
  57. data/spec/tributary/stream_spec.rb +155 -0
  58. data/tributary.gemspec +18 -0
  59. metadata +204 -0
@@ -0,0 +1,22 @@
1
+ article {
2
+ background: white;
3
+ border: 1px dashed black;
4
+ margin: auto;
5
+ padding: 1em;
6
+ width: 30em; }
7
+
8
+ a {
9
+ color: inherit; }
10
+
11
+ body {
12
+ font-family: Georgia;
13
+ text-align: center; }
14
+
15
+ h1 {
16
+ font-variant: small-caps; }
17
+
18
+ li {
19
+ list-style: none; }
20
+
21
+ ul {
22
+ padding: 0; }
@@ -0,0 +1,2 @@
1
+ body {
2
+ background-color: whitesmoke; }
@@ -0,0 +1,5 @@
1
+ date: July 15th, 2010, 12 pm
2
+ title: 600th anniversary (English)
3
+
4
+ 600 years ago [something supposedly important](http://en.wikipedia.org/wiki/Battle_of_Grunwald)
5
+ happened around these parts of the world
@@ -0,0 +1,5 @@
1
+ date: July 15th, 2010, 12 pm
2
+ title: 600th anniversary (intl.)
3
+
4
+ 600 years ago [something supposedly important](http://en.wikipedia.org/wiki/Battle_of_Grunwald)
5
+ happened around these parts of the world
@@ -0,0 +1,4 @@
1
+ date: July 15th, 2010, 6 am
2
+ title: bilinguality
3
+
4
+ this article is also available [in Polish](bilingual.pl)
@@ -0,0 +1,4 @@
1
+ date: July 15th, 2010, 6 am
2
+ title: dwujęzyczność
3
+
4
+ ten wpis jest także dostępny [po angielsku](bilingual.en)
@@ -0,0 +1,4 @@
1
+ date: 2038-01-19T03:14:07Z
2
+ title: Unix Millennium Bug
3
+
4
+ in a second some things won’t be like others
@@ -0,0 +1,4 @@
1
+ date: 2010-07-15
2
+ title: welcome to tributary
3
+
4
+ tributary _welcome_ article
@@ -0,0 +1,3 @@
1
+
2
+
3
+ beep is a short, potentially YAML-less note
@@ -0,0 +1,3 @@
1
+ date: July 15th, 2010, 3 am
2
+
3
+ a dated beep.
@@ -0,0 +1,3 @@
1
+ date: July 23rd, 2010, 1 am
2
+
3
+ this beep is only in English.
@@ -0,0 +1,3 @@
1
+
2
+
3
+ [¿Qué es un link?](http://po-ru.com/) at the start of a beep.
@@ -0,0 +1,3 @@
1
+ date: July 23rd, 2010, 2 am
2
+
3
+ ten beep jest tylko po polsku.
@@ -0,0 +1,4 @@
1
+
2
+
3
+ > An interesting blockquote
4
+ in a beep.
@@ -0,0 +1,12 @@
1
+ content: content
2
+ default: default
3
+ english: English
4
+ english_only: English only
5
+ language: language
6
+ no_limit: no limit
7
+ polish: Polish
8
+ polish_only: Polish only
9
+ previously: previously
10
+ published: published
11
+ recent_items: recent items
12
+ subsequently: subsequently
@@ -0,0 +1,12 @@
1
+ content: treść
2
+ default: domyślny
3
+ english: angielski
4
+ english_only: tylko angielska
5
+ language: język
6
+ no_limit: bez ograniczeń
7
+ polish: polski
8
+ polish_only: tylko polska
9
+ previously: poprzednio
10
+ published: opublikowany
11
+ recent_items: najnowsze
12
+ subsequently: następnie
@@ -0,0 +1,5 @@
1
+ title: about tributary
2
+
3
+ tributary _about_ page
4
+
5
+ about this tributary install
@@ -0,0 +1,4 @@
1
+ %p a tributary article
2
+ %h1= @item.title
3
+ %p #{t.published} #{l @item.date.to_date, :full}
4
+ = @item.body
@@ -0,0 +1,6 @@
1
+ %p a tributary index of articles
2
+ %p recent articles:
3
+ %ul
4
+ - @stream.recent(nil, type: :articles).each do |item|
5
+ %li
6
+ %a{href: item.path}= item.title
File without changes
@@ -0,0 +1,2 @@
1
+ body
2
+ background-color: silver
@@ -0,0 +1 @@
1
+ = @item.body
@@ -0,0 +1,2 @@
1
+ body
2
+ background-color: lightgrey
@@ -0,0 +1,8 @@
1
+ %pre
2
+ :preserve
3
+ Once upon a midnight dreary, while I websurf’d, weak and weary,
4
+ Over many a strange and spurious website of ‘hot chicks galore,’
5
+ While I clicked my fav’rite darling, suddenly there came a warning,
6
+ And my heart was filled with mourning, mourning for my dear amour.
7
+ ‘’Tis not possible,’ I muttered, ‘give me back my cheap hardcore!’ —
8
+ Quoth the Server, ‘<a href='http://plinko.net/board'>404</a>.’
@@ -0,0 +1,6 @@
1
+ article
2
+ text-align: left
3
+ width: 31em
4
+
5
+ pre
6
+ font-family: Georgia, serif
@@ -0,0 +1,6 @@
1
+ %h2 a tributary index
2
+ %p #{t.recent_items}:
3
+ %ul
4
+ - @stream.recent.each do |item|
5
+ %li
6
+ %a{href: item.path}= item.title
@@ -0,0 +1,2 @@
1
+ body
2
+ background-color: gainsboro
@@ -0,0 +1,17 @@
1
+ !!! XML
2
+ %feed{xmlns: 'http://www.w3.org/2005/Atom'}
3
+ %author
4
+ %name&= settings.author
5
+ %generator{uri: 'http://github.com/chastell/tributary'} tributary
6
+ %id= "http://#{request.host}/"
7
+ %link{href: "http://#{request.host}/", rel: 'alternate'}
8
+ %link{href: "http://#{request.host}/#{escape params['feed']}.xml", rel: 'self'}
9
+ %title&= settings.sitename
10
+ %updated= @stream.recent.first.date.iso8601
11
+ - @stream.recent(5).each do |item|
12
+ %entry
13
+ %id= "http://#{request.host}/#{item.path}"
14
+ %link{href: "http://#{request.host}/#{item.path}", rel: 'alternate'}
15
+ %title&= item.title
16
+ %updated= item.date.iso8601
17
+ %content{type: 'html'}&= item.body
@@ -0,0 +1,56 @@
1
+ !!! 5
2
+ %html{lang: @item.lang || Tributary::App.locale || 'en'}
3
+ %head
4
+ %link{href: 'index.xml', rel: 'alternate', title: 'no language preference', type: 'application/atom+xml'}
5
+ %link{href: 'index.en.xml', rel: 'alternate', title: 'English preference', type: 'application/atom+xml'}
6
+ %link{href: 'index.pl.xml', rel: 'alternate', title: 'Polish preference', type: 'application/atom+xml'}
7
+ %link{href: 'index.en.en.xml', rel: 'alternate', title: 'English-only content', type: 'application/atom+xml'}
8
+ %link{href: 'index.pl.pl.xml', rel: 'alternate', title: 'Polish-only content', type: 'application/atom+xml'}
9
+ %link{href: 'layout.css', rel: 'stylesheet'}
10
+ %link{href: "#{@item.type}.css", rel: 'stylesheet'}
11
+ %meta{charset: 'UTF-8'}
12
+ %title= @item.title or settings.sitename + "#{": #{@item.path}" if @item.path}"
13
+ %body
14
+ %h1
15
+ %a{href: '/'}= settings.sitename
16
+ %article
17
+ = yield
18
+ %nav
19
+ %p
20
+ - previous = @stream.previous(@item)
21
+ - subsequent = @stream.subsequent(@item)
22
+ - if previous
23
+ #{t.previously}:
24
+ %a{href: previous.path}= previous.title
25
+ - if previous and subsequent
26
+ \/
27
+ - if subsequent
28
+ #{t.subsequently}:
29
+ %a{href: subsequent.path}= subsequent.title
30
+ %footer
31
+ %p
32
+ #{t.language}:
33
+ - {'en' => t.english, 'pl' => t.polish}.each do |lang, name|
34
+ - if settings.locale == lang
35
+ = name
36
+ - else
37
+ %a{href: "/set?locale=#{lang}"}= name
38
+ |
39
+ - if settings.locale.nil?
40
+ = t.default
41
+ - else
42
+ %a{href: '/set?locale'}= t.default
43
+ %p
44
+ #{t.content}:
45
+ - {'en' => t.english_only, 'pl' => t.polish_only}.each do |lang, name|
46
+ - if settings.lang_limit == [lang]
47
+ = name
48
+ - else
49
+ %a{href: "/set?lang_limit=#{lang}"}= name
50
+ |
51
+ - if settings.lang_limit.nil?
52
+ = t.no_limit
53
+ - else
54
+ %a{href: '/set?lang_limit'}= t.no_limit
55
+ %p
56
+ %a{href: 'about'} designed by chastell in Mazovia
@@ -0,0 +1,22 @@
1
+ article
2
+ background: white
3
+ border: 1px dashed black
4
+ margin: auto
5
+ padding: 1em
6
+ width: 30em
7
+
8
+ a
9
+ color: inherit
10
+
11
+ body
12
+ font-family: Georgia
13
+ text-align: center
14
+
15
+ h1
16
+ font-variant: small-caps
17
+
18
+ li
19
+ list-style: none
20
+
21
+ ul
22
+ padding: 0
@@ -0,0 +1,3 @@
1
+ %p a tributary page
2
+ %h1= @item.title
3
+ = @item.body
@@ -0,0 +1,2 @@
1
+ body
2
+ background-color: whitesmoke
@@ -0,0 +1,266 @@
1
+ # encoding: UTF-8
2
+
3
+ module Tributary describe App do
4
+
5
+ include Rack::Test::Methods
6
+
7
+ def app
8
+ App
9
+ end
10
+
11
+ def session
12
+ Marshal.load rack_test_session.instance_variable_get(:@rack_mock_session).cookie_jar['rack.session'].unpack('m*').first
13
+ end
14
+
15
+ before do
16
+ App.configure do |config|
17
+ config.set :author, 'Ary Tribut'
18
+ config.set :root, 'spec/site'
19
+ config.set :sitename, 'a tributary site'
20
+ end
21
+ end
22
+
23
+ context 'rendering content' do
24
+
25
+ it 'renders the index view when no path given' do
26
+ get '/'
27
+ last_response.should be_ok
28
+ last_response.body.should include 'a tributary index'
29
+ end
30
+
31
+ it 'renders the given view’s index' do
32
+ get '/articles'
33
+ last_response.should be_ok
34
+ last_response.body.should include 'welcome to tributary'
35
+ last_response.body.should_not include 'a…'
36
+ end
37
+
38
+ it 'renders the relevant, path-based view' do
39
+ get '/about'
40
+ last_response.should be_ok
41
+ last_response.body.should include 'a tributary page'
42
+ last_response.body.should include 'tributary <em>about</em> page'
43
+
44
+ get '/welcome'
45
+ last_response.should be_ok
46
+ last_response.body.should include 'a tributary article'
47
+ last_response.body.should include 'tributary <em>welcome</em> article'
48
+ end
49
+
50
+ it 'returns HTTP 404 Not Found on missing items and renders the error template' do
51
+ get '/foo'
52
+ last_response.should_not be_ok
53
+ last_response.status.should == 404
54
+ last_response.body.should include 'Quoth the Server'
55
+ end
56
+
57
+ it 'returns HTTP 404 Not Found on missing feeds and stylesheets and does not return the error template' do
58
+ get '/foo.xml'
59
+ last_response.should_not be_ok
60
+ last_response.status.should == 404
61
+ last_response.body.should be_empty
62
+
63
+ get '/foo.css'
64
+ last_response.should_not be_ok
65
+ last_response.status.should == 404
66
+ last_response.body.should be_empty
67
+ end
68
+
69
+ end
70
+
71
+ context 'view settings' do
72
+
73
+ it 'sets @item.path in the views’ indices' do
74
+ get '/articles'
75
+ last_response.should be_ok
76
+ last_response.body.should include '<title>a tributary site: articles</title>'
77
+ end
78
+
79
+ it 'sets /’s view to :index' do
80
+ get '/'
81
+ last_response.should be_ok
82
+ last_response.body.should include 'index.css'
83
+ end
84
+
85
+ it 'exposes settings to views' do
86
+ get '/'
87
+ last_response.should be_ok
88
+ last_response.body.should include '<title>a tributary site</title>'
89
+ end
90
+
91
+ it 'exposes Stream to views' do
92
+ get '/'
93
+ last_response.should be_ok
94
+ last_response.body.should include 'welcome to tributary'
95
+
96
+ get '/600'
97
+ last_response.should be_ok
98
+ last_response.body.should include 'bilinguality'
99
+ end
100
+
101
+ end
102
+
103
+ context 'feeds' do
104
+
105
+ it 'renders the Atom feed' do
106
+ get '/index.xml'
107
+ last_response.should be_ok
108
+ last_response.headers['Content-Type'].should == 'application/atom+xml;charset=utf-8'
109
+ last_response.body.should == File.read('spec/fixtures/index.xml')
110
+ end
111
+
112
+ it 'renders per-locale Atom feeds' do
113
+ get '/index.en.xml'
114
+ last_response.should be_ok
115
+ last_response.headers['Content-Type'].should == 'application/atom+xml;charset=utf-8'
116
+ last_response.body.should == File.read('spec/fixtures/index.en.xml')
117
+
118
+ get '/index.pl.xml'
119
+ last_response.should be_ok
120
+ last_response.headers['Content-Type'].should == 'application/atom+xml;charset=utf-8'
121
+ last_response.body.should == File.read('spec/fixtures/index.pl.xml')
122
+ end
123
+
124
+ it 'renders lang_limit-ed Atom feeds' do
125
+ get '/index.en.en.xml'
126
+ last_response.should be_ok
127
+ last_response.headers['Content-Type'].should == 'application/atom+xml;charset=utf-8'
128
+ last_response.body.should == File.read('spec/fixtures/index.en.en.xml')
129
+
130
+ get '/index.pl.pl.xml'
131
+ last_response.should be_ok
132
+ last_response.headers['Content-Type'].should == 'application/atom+xml;charset=utf-8'
133
+ last_response.body.should == File.read('spec/fixtures/index.pl.pl.xml')
134
+
135
+ get '/index.en.en+pl.xml'
136
+ last_response.should be_ok
137
+ last_response.headers['Content-Type'].should == 'application/atom+xml;charset=utf-8'
138
+ last_response.body.should == File.read('spec/fixtures/index.en.en+pl.xml')
139
+ end
140
+
141
+ end
142
+
143
+ context 'stylesheets' do
144
+
145
+ it 'renders the CSS stylesheet' do
146
+ get '/layout.css'
147
+ last_response.should be_ok
148
+ last_response.headers['Content-Type'].should == 'text/css;charset=utf-8'
149
+ last_response.body.should == File.read('spec/fixtures/layout.css')
150
+ end
151
+
152
+ it 'renders per-view CSS stylesheets' do
153
+ get '/pages.css'
154
+ last_response.should be_ok
155
+ last_response.headers['Content-Type'].should == 'text/css;charset=utf-8'
156
+ last_response.body.should == File.read('spec/fixtures/pages.css')
157
+ end
158
+
159
+ end
160
+
161
+ context 'localisation and multilinguality' do
162
+
163
+ it 'defaults to nil locale and lang_limit' do
164
+ App.locale.should == nil
165
+ App.lang_limit.should == nil
166
+ end
167
+
168
+ it 'sets the right App settings and redirects properly' do
169
+ get '/set?locale=pl', {}, 'HTTP_REFERER' => '/bilingual'
170
+ last_response.location.should == 'http://example.org/bilingual'
171
+ follow_redirect!
172
+ App.locale.should == 'pl'
173
+ last_response.should be_ok
174
+ last_response.body.should include '<title>dwujęzyczność</title>'
175
+
176
+ get '/set?lang_limit=pl'
177
+ follow_redirect!
178
+ App.lang_limit.should == ['pl']
179
+ last_response.should be_ok
180
+ last_response.body.should_not include '600th anniversary (English)'
181
+
182
+ get '/set?locale'
183
+ follow_redirect!
184
+ App.locale.should == nil
185
+
186
+ get '/set?lang_limit'
187
+ follow_redirect!
188
+ App.lang_limit.should == nil
189
+ end
190
+
191
+ it 'localises the output based on locale (defaulting to English)' do
192
+ get '/set?locale=pl'
193
+ get '/bilingual'
194
+ last_response.should be_ok
195
+ last_response.body.should include 'opublikowany 15 lipca 2010'
196
+
197
+ get '/set?locale=en'
198
+ get '/bilingual'
199
+ last_response.should be_ok
200
+ last_response.body.should include 'published 15th of July, 2010'
201
+
202
+ get '/set?locale'
203
+ get '/bilingual'
204
+ last_response.should be_ok
205
+ last_response.body.should include 'published 15th of July, 2010'
206
+ end
207
+
208
+ it 'sets the right value for the <html> element’s lang attribute' do
209
+ get '/set?locale=en'
210
+ get '/'
211
+ last_response.should be_ok
212
+ last_response.body.should include "<html lang='en'>"
213
+
214
+ get '/set?locale=pl'
215
+ get '/'
216
+ last_response.should be_ok
217
+ last_response.body.should include "<html lang='pl'>"
218
+
219
+ get '/set?locale'
220
+ get '/'
221
+ last_response.should be_ok
222
+ last_response.body.should include "<html lang='en'>"
223
+
224
+ get '/set?locale=en'
225
+ get '/bilingual.pl'
226
+ last_response.should be_ok
227
+ last_response.body.should include "<html lang='pl'>"
228
+ end
229
+
230
+ end
231
+
232
+ context 'configuration' do
233
+
234
+ it 'has proper defaults' do
235
+ App.cache?.should be_false
236
+ App.lang_limit.should be_nil
237
+ App.locale.should be_nil
238
+ App.plugins.should be_empty
239
+ App.user_prefs.should == [:lang_limit, :locale]
240
+ App.stream.should be_nil
241
+ end
242
+
243
+ it 'sets only whitelisted settings' do
244
+ get '/set?foo=bar&locale=en'
245
+ get '/'
246
+ session.should have_key :locale
247
+ session.should_not have_key :foo
248
+ end
249
+
250
+ end
251
+
252
+ context 'stream caching' do
253
+
254
+ it 'caches the Stream in production by default' do
255
+ App.stub production?: true
256
+ App.configure {}
257
+ App.stream.should be_a Stream
258
+ end
259
+
260
+ it 'does not cache the Stream in development/testing by default' do
261
+ App.stream.should be_nil
262
+ end
263
+
264
+ end
265
+
266
+ end end