tumblargh 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +8 -12
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/examples/middleman_config.rb +3 -4
- data/lib/middleman/extensions/tumblargh.rb +39 -0
- data/lib/rack/tumblargh.rb +10 -3
- data/lib/tumblargh.rb +5 -0
- data/lib/tumblargh/renderer.rb +1 -275
- data/lib/tumblargh/renderer/base.rb +0 -1
- data/lib/tumblargh/renderer/blocks.rb +276 -0
- data/lib/tumblargh/renderer/blocks/audio.rb +7 -1
- data/lib/tumblargh/renderer/blocks/base.rb +2 -1
- data/lib/tumblargh/renderer/blocks/chat.rb +44 -0
- data/lib/tumblargh/renderer/blocks/photoset.rb +27 -0
- data/lib/tumblargh/resource.rb +2 -0
- data/lib/tumblargh/resource/blog.rb +1 -1
- data/lib/tumblargh/resource/dialogue.rb +8 -0
- data/lib/tumblargh/resource/photo.rb +19 -0
- data/lib/tumblargh/resource/post.rb +17 -9
- data/spec/renderer/blocks_spec.rb +78 -0
- data/spec/renderer/document_spec.rb +6 -42
- data/tumblargh.gemspec +10 -4
- metadata +34 -54
- data/lib/middleman/features/tumblargh.rb +0 -41
data/README.md
CHANGED
@@ -27,14 +27,15 @@ The recommended way to use tumblargh is in conjuction with
|
|
27
27
|
templating languages (Haml, Sass, Compass, Slim, CoffeeScript, and more).
|
28
28
|
|
29
29
|
Tumblargh includes a simple Middleman extension that turns any Middleman project
|
30
|
-
into a local Tumblr theme building machine.
|
30
|
+
into a local Tumblr theme building machine. As of `0.2.0`, Tumblargh requires
|
31
|
+
Middleman `>= 3.0`.
|
31
32
|
|
32
33
|
Tumblargh will automatically parse any html files served by Middleman, and
|
33
34
|
populate them with content from the Tumblr of your choosing. It will not
|
34
|
-
parse any HTML during Middleman's build process. The output of`middleman build`
|
35
|
+
parse any HTML during Middleman's build process. The output of `middleman build`
|
35
36
|
is ready for use on your blog, or submission to the Tumblr theme store.
|
36
37
|
|
37
|
-
To get up
|
38
|
+
To get up and running with Middleman, first create a new Middleman project:
|
38
39
|
|
39
40
|
```
|
40
41
|
$ middleman init MY_PROJECT_NAME
|
@@ -46,24 +47,19 @@ If one does not already exist, create a Gemfile and add the following as needed:
|
|
46
47
|
source "http://rubygems.org"
|
47
48
|
|
48
49
|
gem 'middleman'
|
49
|
-
gem 'tumblargh'
|
50
|
+
gem 'tumblargh'
|
50
51
|
```
|
51
52
|
|
52
|
-
Note that there has not yet been an official release of tumblargh to RubyGems,
|
53
|
-
so currently, specifying the gem via git is necessary.
|
54
|
-
|
55
53
|
Run `bundle install`.
|
56
54
|
|
57
55
|
The bare minimum setup in your Middleman config.rb is:
|
58
56
|
|
59
57
|
```ruby
|
60
58
|
require 'tumblargh'
|
61
|
-
require 'middleman/features/tumblargh'
|
62
|
-
|
63
|
-
activate :tumblargh
|
64
59
|
|
65
|
-
|
66
|
-
|
60
|
+
activate :tumblargh,
|
61
|
+
api_key: 'API KEY', # This is your OAuth consumer key
|
62
|
+
blog: 'staff.tumblr.com'
|
67
63
|
```
|
68
64
|
|
69
65
|
It is highly recommended to run the Middleman server via `bundle exec`.
|
data/Rakefile
CHANGED
@@ -28,7 +28,7 @@ require 'jeweler'
|
|
28
28
|
Jeweler::Tasks.new do |s|
|
29
29
|
s.name = 'tumblargh'
|
30
30
|
s.summary = 'Groan-less Tumblr theme development.'
|
31
|
-
s.description =
|
31
|
+
s.description = "If you've ever had to build a Tumblr theme, you've probably cried out in pain while tweaking locally, copying, pasting into the theme editor, saving, switching tabs and finally refreshing and waiting for your tesing blog to reload. Tumblargh aims to reduce suffering involved with building a theme by offering a way to fully develop, lint and test Tumblr themes locally, with real posts from any existing Tumblog."
|
32
32
|
s.authors = ['Jason Webster']
|
33
33
|
s.email = 'jason@metalabdesign.com'
|
34
34
|
s.homepage = 'http://github.com/jasonwebster/tumblargh'
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'rack/tumblargh'
|
2
|
+
|
3
|
+
module Middleman
|
4
|
+
module Extensions
|
5
|
+
module Tumblargh
|
6
|
+
class << self
|
7
|
+
|
8
|
+
def registered(app, options={})
|
9
|
+
::Tumblargh::API::set_api_key(options[:api_key])
|
10
|
+
|
11
|
+
app.after_configuration do
|
12
|
+
unless build?
|
13
|
+
use ::Rack::Tumblargh, options
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
alias :included :registered
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# So, page proxies don't support globs or regex matching anymore, due to how the
|
26
|
+
# new Sitemap stuff works (at least as far as I can tell). This is what I came
|
27
|
+
# up with as a workaround.
|
28
|
+
module Sitemap
|
29
|
+
class Store
|
30
|
+
alias_method :orig_find_resource_by_destination_path, :find_resource_by_destination_path
|
31
|
+
|
32
|
+
def find_resource_by_destination_path(request_path)
|
33
|
+
request_path = "/index.html" if request_path.match(/^\/post\//)
|
34
|
+
orig_find_resource_by_destination_path(request_path)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
data/lib/rack/tumblargh.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
module Rack
|
2
2
|
class Tumblargh
|
3
|
-
Tumblargh = ::Tumblargh
|
4
3
|
|
5
4
|
def initialize(app, options={})
|
6
5
|
@app = app
|
@@ -11,10 +10,18 @@ module Rack
|
|
11
10
|
attr_reader :options
|
12
11
|
|
13
12
|
def call(env)
|
13
|
+
request = Rack::Request.new(env)
|
14
|
+
|
15
|
+
['/tweets.js', %r{/api.*}].each do |route|
|
16
|
+
if request.path.match route
|
17
|
+
url = "http://#{@options[:blog]}#{request.path}?#{request.query_string}"
|
18
|
+
return [301, { "Location" => url }, []]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
14
22
|
status, headers, response = @app.call(env)
|
15
23
|
|
16
24
|
if should_parse?(status, headers)
|
17
|
-
|
18
25
|
content = response.respond_to?(:body) ? response.body : response
|
19
26
|
render_opts = { :permalink => permalink?(env['PATH_INFO']) }
|
20
27
|
|
@@ -44,7 +51,7 @@ module Rack
|
|
44
51
|
end
|
45
52
|
|
46
53
|
def render(content, opts)
|
47
|
-
Tumblargh::render_html(content.first, options[:blog], opts)
|
54
|
+
::Tumblargh::render_html(content.first, options[:blog], opts)
|
48
55
|
end
|
49
56
|
|
50
57
|
end
|
data/lib/tumblargh.rb
CHANGED
data/lib/tumblargh/renderer.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'cgi'
|
2
2
|
|
3
3
|
require 'tumblargh/renderer/base'
|
4
|
+
require 'tumblargh/renderer/blocks'
|
4
5
|
require 'tumblargh/renderer/document'
|
5
6
|
require 'tumblargh/renderer/literal'
|
6
7
|
require 'tumblargh/renderer/tag'
|
@@ -37,280 +38,5 @@ module Tumblargh
|
|
37
38
|
klass.new(node, context, *args)
|
38
39
|
end
|
39
40
|
|
40
|
-
|
41
|
-
module Blocks
|
42
|
-
|
43
|
-
require 'tumblargh/renderer/blocks/base'
|
44
|
-
|
45
|
-
class Description < Base
|
46
|
-
def should_render?
|
47
|
-
!description.blank?
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
class NumberedPost < Base
|
52
|
-
attr_reader :num
|
53
|
-
|
54
|
-
def initialize(node, context, *args)
|
55
|
-
@num = args[0]
|
56
|
-
super(node, context)
|
57
|
-
end
|
58
|
-
|
59
|
-
def should_render?
|
60
|
-
num == context.posts.index(context_post) + 1
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
# Common post blocks
|
67
|
-
class Title < Base
|
68
|
-
def should_render?
|
69
|
-
!(title.nil? || title.blank?)
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
class Caption < Base
|
74
|
-
def should_render?
|
75
|
-
!(caption.nil? || caption.blank?)
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
# Base post type
|
80
|
-
class Post < Base
|
81
|
-
def should_render?
|
82
|
-
# TODO Looks like photosets come as type = 'photo'
|
83
|
-
self.class.name.split('::').last.downcase == context.type
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
# Source block for Quote posts
|
88
|
-
class Source < Base
|
89
|
-
def should_render?
|
90
|
-
!source.blank?
|
91
|
-
end
|
92
|
-
|
93
|
-
def source
|
94
|
-
context.source
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
class Text < Post
|
99
|
-
end
|
100
|
-
|
101
|
-
class Photo < Post
|
102
|
-
def photo_url(size=500)
|
103
|
-
context.photo_url(size)
|
104
|
-
end
|
105
|
-
|
106
|
-
def photo_alt
|
107
|
-
strip_html(context.caption)
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
class Photoset < Photo
|
112
|
-
end
|
113
|
-
|
114
|
-
class Video < Photo
|
115
|
-
end
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
class Quote < Post
|
120
|
-
def quote
|
121
|
-
context.text
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
class Chat < Post
|
126
|
-
end
|
127
|
-
|
128
|
-
class Link < Post
|
129
|
-
end
|
130
|
-
|
131
|
-
|
132
|
-
# Meta-block for Appearance booleans, like {block:IfSomething}
|
133
|
-
class Boolean < Base
|
134
|
-
attr_reader :variable
|
135
|
-
|
136
|
-
def initialize(node, context, *args)
|
137
|
-
@variable = args[0]
|
138
|
-
super(node, context)
|
139
|
-
end
|
140
|
-
|
141
|
-
def should_render?
|
142
|
-
context.boolean(variable.downcase)
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
|
-
class InverseBoolean < Boolean
|
147
|
-
def should_render?
|
148
|
-
! super
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
|
153
|
-
# Rendered on permalink pages. (Useful for displaying the current post's
|
154
|
-
# title in the page title)
|
155
|
-
class PostTitle < Base
|
156
|
-
def should_render?
|
157
|
-
false
|
158
|
-
end
|
159
|
-
|
160
|
-
def post_title
|
161
|
-
# TODO: Implementation
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
# Identical to {PostTitle}, but will automatically generate a summary
|
166
|
-
# if a title doesn't exist.
|
167
|
-
class PostSummary < PostTitle
|
168
|
-
def post_summary
|
169
|
-
# TODO: Implementation
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
class ContentSource < Base
|
176
|
-
def should_render?
|
177
|
-
!source_title.nil?
|
178
|
-
end
|
179
|
-
|
180
|
-
contextual_tag :source_url
|
181
|
-
contextual_tag :source_title
|
182
|
-
|
183
|
-
# TODO: Impl.
|
184
|
-
def black_logo_url
|
185
|
-
end
|
186
|
-
|
187
|
-
def logo_width
|
188
|
-
end
|
189
|
-
|
190
|
-
def logo_height
|
191
|
-
end
|
192
|
-
|
193
|
-
end
|
194
|
-
|
195
|
-
class SourceLogo < Base
|
196
|
-
# TODO: Impl.
|
197
|
-
end
|
198
|
-
|
199
|
-
class NoSourceLogo < SourceLogo
|
200
|
-
def should_render?
|
201
|
-
! super
|
202
|
-
end
|
203
|
-
end
|
204
|
-
|
205
|
-
class HasTags < Base
|
206
|
-
def should_render?
|
207
|
-
!(tags.nil? || tags.blank?)
|
208
|
-
end
|
209
|
-
end
|
210
|
-
|
211
|
-
|
212
|
-
# Rendered on index (post) pages.
|
213
|
-
class IndexPage < Base
|
214
|
-
def should_render?
|
215
|
-
! context.permalink?
|
216
|
-
end
|
217
|
-
end
|
218
|
-
|
219
|
-
# Rendered on post permalink pages.
|
220
|
-
class PermalinkPage < Base
|
221
|
-
def should_render?
|
222
|
-
context.permalink?
|
223
|
-
end
|
224
|
-
end
|
225
|
-
|
226
|
-
class SearchPage < Base
|
227
|
-
def should_render?
|
228
|
-
false
|
229
|
-
end
|
230
|
-
end
|
231
|
-
|
232
|
-
class NoSearchResults < Base
|
233
|
-
def should_render?
|
234
|
-
false
|
235
|
-
end
|
236
|
-
end
|
237
|
-
|
238
|
-
class TagPage < Base
|
239
|
-
def should_render?
|
240
|
-
false
|
241
|
-
end
|
242
|
-
end
|
243
|
-
|
244
|
-
# Rendered if you have defined any custom pages.
|
245
|
-
class HasPages < Base
|
246
|
-
# TODO: Implementation
|
247
|
-
|
248
|
-
def should_render?
|
249
|
-
false
|
250
|
-
end
|
251
|
-
end
|
252
|
-
|
253
|
-
# Rendered for each custom page.
|
254
|
-
class Pages < Base
|
255
|
-
# TODO: Implementation
|
256
|
-
|
257
|
-
def should_render?
|
258
|
-
false
|
259
|
-
end
|
260
|
-
|
261
|
-
# custom page url
|
262
|
-
def url
|
263
|
-
end
|
264
|
-
|
265
|
-
# custom page name/label
|
266
|
-
def label
|
267
|
-
end
|
268
|
-
|
269
|
-
end
|
270
|
-
|
271
|
-
# Rendered if you have Twitter integration enabled.
|
272
|
-
class Twitter < Base
|
273
|
-
# TODO: Implementation
|
274
|
-
|
275
|
-
def should_render?
|
276
|
-
false
|
277
|
-
end
|
278
|
-
|
279
|
-
def twitter_username
|
280
|
-
end
|
281
|
-
|
282
|
-
end
|
283
|
-
|
284
|
-
|
285
|
-
# {block:Likes} {/block:Likes} Rendered if you are sharing your likes.
|
286
|
-
# {Likes} Standard HTML output of your likes.
|
287
|
-
# {Likes limit="5"} Standard HTML output of your last 5 likes.
|
288
|
-
# Maximum: 10
|
289
|
-
# {Likes width="200"} Standard HTML output of your likes with Audio and Video players scaled to 200-pixels wide.
|
290
|
-
# Scale images with CSS max-width or similar.
|
291
|
-
# {Likes summarize="100"} Standard HTML output of your likes with text summarize to 100-characters.
|
292
|
-
# Maximum: 250
|
293
|
-
class Likes < Base
|
294
|
-
# TODO: Implementation
|
295
|
-
|
296
|
-
def should_render?
|
297
|
-
false
|
298
|
-
end
|
299
|
-
|
300
|
-
def likes
|
301
|
-
end
|
302
|
-
|
303
|
-
end
|
304
|
-
|
305
|
-
require 'tumblargh/renderer/blocks/answer'
|
306
|
-
require 'tumblargh/renderer/blocks/audio'
|
307
|
-
require 'tumblargh/renderer/blocks/dates'
|
308
|
-
require 'tumblargh/renderer/blocks/navigation'
|
309
|
-
require 'tumblargh/renderer/blocks/notes'
|
310
|
-
require 'tumblargh/renderer/blocks/posts'
|
311
|
-
require 'tumblargh/renderer/blocks/reblogs'
|
312
|
-
require 'tumblargh/renderer/blocks/tags'
|
313
|
-
|
314
|
-
end
|
315
41
|
end
|
316
42
|
end
|