Thimblr 0.6.12 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,12 +2,6 @@
2
2
  Tumblr:
3
3
  PostsPerPage: 10
4
4
 
5
- ## Settings affecting Thimblr
6
- # The location of your theme files
7
- ThemesLocation: themes
8
- # The location of your data files
9
- DataLocation: data
10
-
11
5
  # This allows the thimblr server to open your chosen editor to edit
12
6
  # the theme you're currently viewing. There is a (very small!) risk
13
7
  # that this could do malicious things, so you can disable it if you
@@ -5,7 +5,9 @@ require 'digest/md5'
5
5
  require 'pathname'
6
6
  require 'launchy'
7
7
  require 'thimblr/parser'
8
+ require 'thimblr/importer'
8
9
  require 'rbconfig'
10
+ require 'fileutils'
9
11
 
10
12
  class Thimblr::Application < Sinatra::Base
11
13
  Editors = {
@@ -13,10 +15,10 @@ class Thimblr::Application < Sinatra::Base
13
15
  'bbedit' => {'command' => "bbedit",'platform' => 'mac','name' => "BBEdit"},
14
16
  'textedit' => {'command' => "open -a TextEdit.app",'platform' => 'mac','name' => "TextEdit"}
15
17
  }
16
- Locations = [
17
- {"dir" => "~/Library/Application Support/Thimblr/", 'name' => "Application Support", 'platform' => "mac"},
18
- {'dir' => "~/.thimblr/",'name' => "Home directory", 'platform' => "nix"}
19
- ]
18
+ Locations = {
19
+ "mac" => {"dir" => "~/Library/Application Support/Thimblr/", 'name' => "Application Support", 'platform' => "mac"},
20
+ "nix" => {'dir' => "~/.thimblr/",'name' => "Home directory", 'platform' => "nix"}
21
+ }
20
22
 
21
23
  case RbConfig::CONFIG['target_os']
22
24
  when /darwin/i
@@ -28,8 +30,8 @@ class Thimblr::Application < Sinatra::Base
28
30
  end
29
31
 
30
32
  def self.parse_config(s)
31
- set :themes, File.expand_path((File.directory? s['ThemesLocation']) ? s['ThemesLocation'] : "./themes")
32
- set :data, File.expand_path((File.directory? s['DataLocation'] || "") ? s['DataLocation'] : "")
33
+ set :themes, File.expand_path(File.join(Locations[Platform]['dir'],"themes"))
34
+ set :data, File.expand_path(File.join(Locations[Platform]['dir'],"data"))
33
35
  set :allowediting, (s['AllowEditing']) ? true : false
34
36
  set :editor, s['Editor'] if s['Editor']
35
37
  set :tumblr, Thimblr::Parser::Defaults.merge(s['Tumblr'] || {})
@@ -40,10 +42,29 @@ class Thimblr::Application < Sinatra::Base
40
42
  set :root, File.join(File.dirname(__FILE__),"..")
41
43
  Dir.chdir root
42
44
  set :config, File.join(root,'config')
45
+ set :settingsfile, File.expand_path(File.join(Locations[Platform]['dir'],'settings.yaml'))
46
+
47
+ # Generate Data & Theme directories if required
48
+ if not File.directory?(File.expand_path(File.join(Locations[Platform]['dir'],"themes")))
49
+ FileUtils.cp_r(File.join(root,'themes'),File.expand_path(Locations[Platform]['dir']))
50
+ end
51
+
52
+ if not File.directory?(File.expand_path(File.join(Locations[Platform]['dir'],"data")))
53
+ FileUtils.mkdir_p(File.expand_path(File.join(Locations[Platform]['dir'],"data")))
54
+ FileUtils.cp(File.join(config,'demo.yaml'),File.expand_path(File.join(Locations[Platform]['dir'],'data','demo.yml')))
55
+ end
56
+
57
+ begin # Try to load the settings file, if it's crap then overwrite it with the defaults
58
+ s.parse_config(YAML::load(open(settingsfile)))
59
+ rescue
60
+ FileUtils.cp(File.join(config,'settings.default.yaml'),settingsfile)
61
+ retry
62
+ end
43
63
 
44
- s.parse_config(YAML::load(open(File.join(config,'settings.yaml'))))
45
64
  enable :sessions
46
65
  set :bind, '127.0.0.1'
66
+
67
+ Launchy.open("http://localhost:#{port}")
47
68
  end
48
69
 
49
70
  helpers do
@@ -53,7 +74,11 @@ class Thimblr::Application < Sinatra::Base
53
74
  end
54
75
 
55
76
  get '/' do
56
- erb :index
77
+ redirect 'index.html'
78
+ end
79
+
80
+ get '/menu' do
81
+ erb :menu
57
82
  end
58
83
 
59
84
  get '/help' do
@@ -77,7 +102,7 @@ class Thimblr::Application < Sinatra::Base
77
102
  end
78
103
 
79
104
  get '/data.set' do
80
- if File.exists?(File.join(settings.data,"#{params['data']}.yml")) or params['data'] == 'demo'
105
+ if File.exists?(File.join(settings.data,"#{params['data']}.yml"))
81
106
  response.set_cookie('data',params['data'])
82
107
  else
83
108
  halt 404, "Not found"
@@ -89,7 +114,6 @@ class Thimblr::Application < Sinatra::Base
89
114
  Dir.glob("#{settings.data}/*.yml").collect do |datum|
90
115
  data[File.basename(datum,".yml")] = Digest::MD5.hexdigest(open(datum).read)
91
116
  end
92
- data['demo'] = Digest::MD5.hexdigest(open(File.join(settings.config,"demo.yml")).read)
93
117
  data.to_json
94
118
  end
95
119
 
@@ -118,12 +142,11 @@ class Thimblr::Application < Sinatra::Base
118
142
  get %r{/(tumblr)?settings.set} do |tumblr|
119
143
  halt 501 if tumblr == "tumblr" # TODO: Tumblr settings save
120
144
 
145
+ params['AllowEditing'] = (params['AllowEditing'] == "on")
121
146
  settings.parse_config(params)
122
- open(File.join(settings.config,"settings.yaml"),"w") do |f|
147
+ open(settings.settingsfile,"w") do |f|
123
148
  f.write YAML.dump({
124
149
  "Tumblr" => settings.tumblr,
125
- "ThemesLocation" => get_relative(settings.themes),
126
- "DataLocation" => get_relative(settings.data),
127
150
  "AllowEditing" => settings.allowediting,
128
151
  "Editor" => settings.editor,
129
152
  "Port" => settings.port
@@ -133,9 +156,17 @@ class Thimblr::Application < Sinatra::Base
133
156
  "Settings saved"
134
157
  end
135
158
 
136
- # TODO: Downloads feed data from a tumblr site
137
- get '/import' do
138
- halt 501, "Sorry, I haven't written this bit yet!"
159
+ # Downloads feed data from a tumblr site
160
+ get %r{/import/([a-zA-Z0-9-]+)} do |username|
161
+ begin
162
+ data = Thimblr::Import.username(username)
163
+ open(File.join(settings.data,"#{username}.yml"),'w') do |f|
164
+ f.write data
165
+ end
166
+ rescue Exception => e
167
+ halt 404, e.message
168
+ end
169
+ "Imported as '#{username}'"
139
170
  end
140
171
 
141
172
  before do
@@ -179,7 +210,4 @@ class Thimblr::Application < Sinatra::Base
179
210
  get '/thimblr/*' do
180
211
  @parser.render_page(params[:splat])
181
212
  end
182
-
183
- # TODO: Only if Sinatra runs successfully
184
- Launchy.open("http://localhost:#{port}")
185
213
  end
@@ -0,0 +1,89 @@
1
+ require 'open-uri'
2
+ require 'nokogiri'
3
+ require 'yaml'
4
+ require 'uri'
5
+
6
+ module Thimblr
7
+ class Import
8
+ def self.username(username)
9
+ data = {}
10
+ begin
11
+ xml = Nokogiri::XML(open("http://#{username}.tumblr.com/api/read"))
12
+ rescue OpenURI::HTTPError
13
+ raise "Username not found"
14
+ end
15
+
16
+ data['Title'] = xml.search('tumblelog')[0]['title']
17
+ data['Description'] = xml.search('tumblelog')[0].content
18
+
19
+ data['Posts'] = []
20
+ xml.search('posts post').each do |xpost|
21
+ post = {
22
+ 'PostId' => xpost['id'].to_i,
23
+ 'Permalink' => xpost['url'],
24
+ 'Type' => xpost['type'].capitalize,
25
+ 'Timestamp' => xpost['unix-timestamp'].to_i,
26
+ 'Tags' => xpost.search('tag').collect{ |tag| tag.content }
27
+ }
28
+
29
+ post['Type'] = "Text" if post['Type'] == "Regular"
30
+ post['Type'] = "Chat" if post['Type'] == "Conversation"
31
+
32
+ post.store('Title', xpost.search("#{xpost['type']}-title")[0].content) rescue nil
33
+
34
+ post.store('Caption',xpost.search("#{xpost['type']}-caption")[0].content) rescue nil
35
+
36
+ post.store('LinkURL',xpost.search("#{xpost['type']}-link-url")[0].content) rescue nil
37
+
38
+ post.store('Source',xpost.search("#{xpost['type']}-source")[0].content) rescue nil
39
+
40
+ case post['Type']
41
+ when "Photo"
42
+ xpost.search('photo-url').each do |photo|
43
+ post["PhotoURL-#{photo['max-width']}"] = photo.content
44
+ end
45
+ when "Link"
46
+ begin
47
+ post['Name'] = xpost.search("link-text")[0].content
48
+ rescue
49
+ end
50
+ when "Video"
51
+ post['Player'] = xpost.search("video-player")[0].content
52
+ when "Text"
53
+ post['Body'] = xpost.search("regular-body")[0].content
54
+ end
55
+
56
+ data['Posts'].push post
57
+ end
58
+
59
+ # Pages
60
+ begin
61
+ xml = Nokogiri::XML(open("http://#{username}.tumblr.com/api/pages"))
62
+ data['Pages'] = []
63
+
64
+ xml.search('pages').children.each do |re|
65
+ case re.name
66
+ when "redirect"
67
+ data['Pages'].push({
68
+ "Label" => re['link-title'],
69
+ "URL" => re['redirect-to']
70
+ })
71
+ when "page"
72
+ data['Pages'].push({
73
+ "Label" => re['link-title'],
74
+ "URL" => URI.split(re['url'])[5],
75
+ "Title" => re['title'],
76
+ "InTheme" => (re['render-in-theme'] == "true"),
77
+ "Body" => re.content
78
+ })
79
+ end
80
+ end
81
+ # Do pages
82
+ rescue OpenURI::HTTPError
83
+ # No pages
84
+ end
85
+
86
+ YAML::dump(data)
87
+ end
88
+ end
89
+ end
@@ -41,9 +41,9 @@ module Thimblr
41
41
  'Pagination' => (@posts.length > @settings['PostsPerPage'].to_i),
42
42
  'SubmissionsEnabled' => template['SubmissionsEnabled'],
43
43
  'AskEnabled' => !@constants['AskLabel'].empty?,
44
- 'HasPages' => @pages.length > 0,
45
- 'Following' => @following.length > 0,
46
- 'Followed' => @followed.length > 0,
44
+ 'HasPages' => (@pages.length > 0 rescue false),
45
+ 'Following' => (@following.length > 0 rescue false),
46
+ 'Followed' => (@followed.length > 0 rescue false),
47
47
  'More' => true
48
48
  }
49
49
 
@@ -16,12 +16,32 @@ $(document).ready(function(){
16
16
  e.preventDefault();
17
17
  })
18
18
 
19
+ $('#import').bind('submit',function(e) {
20
+ $('#TumblrUser').disabled = true
21
+ $.ajax({
22
+ url:'/import/'+$('#TumblrUser').val(),
23
+ success: function(d) {
24
+ $('#TumblrUser,#importinput').effect("highlight", {color:'#00ff00'}, 1000)
25
+ $('#TumblrUser').val('')
26
+ $('#TumblrUser').disabled = false
27
+ },
28
+ error: function(d) {
29
+ $('#TumblrUser,#importinput').effect("highlight", {color:'#ff0000'}, 2000)
30
+ $('#TumblrUser').val('')
31
+ $('#TumblrUser').disabled = false
32
+ }
33
+ })
34
+ })
35
+
19
36
  $('table.settings a.preset').bind('click',function(e) {
20
37
  e.preventDefault();
21
38
  $('#'+$(this).parent().attr('rel')).val(this.rel).effect("highlight", {}, 500);
22
39
  })
23
40
 
24
41
  $('#settings input').bind('change',function(e) {
25
- $.get($('#settings').attr('action'),$('#settings').serialize())
42
+ $.get($('#settings').attr('action'),$('#settings').serialize(),function(d,status) {
43
+ $('#saved').effect("highlight", {}, 500);
44
+ $('#saved em').text(d)
45
+ })
26
46
  })
27
47
  })
@@ -11,7 +11,7 @@ $(document).ready(function(){
11
11
 
12
12
  $('#theme-select').bind('submit',function(e){
13
13
  $.get('/theme.set',{'theme':$('#theme-selector').children(':selected').val()},function() {
14
- $('#theme-preview').attr('src','/thimblr');
14
+ parent.tumblr.location.href = '/thimblr'
15
15
  $('#theme-selector').children(':selected').removeClass('altered')
16
16
  })
17
17
  return false;
@@ -27,14 +27,13 @@ $(document).ready(function(){
27
27
  $('#data-select').bind('submit',function(e){
28
28
  currtheme = $('#data-selector').children(':selected').val();
29
29
  $.get('/data.set',{'data':currtheme},function() {
30
- $('#data-preview').attr('src','/thimblr');
30
+ parent.tumblr.location.href = '/thimblr'
31
31
  $('#data-selector').children(':selected').removeClass('altered')
32
32
  })
33
33
  return false;
34
34
  });
35
35
 
36
36
  $('#data-selector').bind('click',function(e){
37
- alert('argh')
38
37
  if (e.target.nodeName.toLowerCase() === 'option')
39
38
  $('#data-select').trigger('submit');
40
39
  });
@@ -0,0 +1,13 @@
1
+ <html>
2
+ <head>
3
+ <title>Thimblr - A Tumblr Theme Editor</title>
4
+ </head>
5
+ <frameset rows="32px,*" frameborder="no" framespacing="0" border="0">
6
+
7
+ <frame src="menu" />
8
+ <frame src="help" name="tumblr" id="theme-preview" />
9
+
10
+ </frameset>
11
+
12
+ </html>
13
+
@@ -72,42 +72,6 @@ Hope you guys don't mind… -->
72
72
  </div>
73
73
  </td>
74
74
  </tr>
75
-
76
- <a name="ThemesLocation"></a>
77
- <tr id="opt-ThemesLocation">
78
- <td><label for="ThemesLocation">Location of Themes</label></td>
79
- <td><input id="ThemesLocation" type="text" name="ThemesLocation" value="<%=get_relative(settings.themes)%>/" /></td>
80
- <td class="explain">
81
- <div class="contain">
82
- <img src="/images/preset.png" class="presetIcon"/>
83
- <div class="presetbox">
84
- <div class="presets" rel="ThemesLocation">
85
- <% Thimblr::Application::Locations.each do |loc| %>
86
- <a href="#" rel="<%=loc['dir']%>themes/" title="<%=loc['name']%>" class="preset <%=loc['platform']%>"><img src="/images/os/<%=loc['platform']%>.png"/></a>
87
- <% end %>
88
- </div>
89
- </div>
90
- </div>
91
- </td>
92
- </tr>
93
-
94
- <a name="DataLocation"></a>
95
- <tr id="opt-DataLocation">
96
- <td><label for="DataLocation">Location of Data</label></td>
97
- <td><input id="DataLocation" type="text" name="DataLocation" value="<%=get_relative(settings.data)%>/" /></td>
98
- <td class="explain">
99
- <div class="contain">
100
- <img src="/images/preset.png" class="presetIcon"/>
101
- <div class="presetbox">
102
- <div class="presets" rel="DataLocation">
103
- <% Thimblr::Application::Locations.each do |loc| %>
104
- <a href="#" rel="<%=loc['dir']%>data/" title="<%=loc['name']%>" class="preset <%=loc['platform']%>"><img src="/images/os/<%=loc['platform']%>.png"/></a>
105
- <% end %>
106
- </div>
107
- </div>
108
- </div>
109
- </td>
110
- </tr>
111
75
 
112
76
  <a name="Port"></a>
113
77
  <tr id="opt-Port">
@@ -119,7 +83,7 @@ Hope you guys don't mind… -->
119
83
  </tr>
120
84
  </table>
121
85
  </form>
122
- <p><em>Changes are saved automatically</em></p>
86
+ <p id="saved"><em>Changes are saved automatically</em></p>
123
87
  </div>
124
88
  </div>
125
89
  <div style="background-color: rgb(192, 205, 129);" id="right_column">
@@ -130,10 +94,10 @@ Hope you guys don't mind… -->
130
94
  </div>
131
95
  <div class="goody_container">
132
96
  <h2>Import Data</h2>
133
- <p>Once I've gone outside for a while I'll write a script here that will download a tumblr user's posts here. Not ready yet tho, sorry :(</p>
134
- <form action="/import" id="import">
97
+ <p>Imports posts data from a specific tumblelog, so you can test themes with real-world data!</p>
98
+ <form action="/import/" id="import">
135
99
  <label for="TumblrUser">Tumblr Username</label>
136
- <div style="margin-bottom: 5px;" class="goody_data">
100
+ <div style="margin-bottom: 5px;" class="goody_data" id="importinput">
137
101
  <input type="text" value="" name="TumblrUser" id="TumblrUser" />
138
102
  </div>
139
103
  </form>
@@ -42,8 +42,5 @@
42
42
  </form>
43
43
  <a id="docs" href="/help#Instructions" target="tumblr">Help</a>
44
44
  </div>
45
- <div id="theme-container">
46
- <iframe id="theme-preview" src="/help" border="0" frameborder="0" name="tumblr"></iframe>
47
- </div>
48
45
  </body>
49
46
  </html>
metadata CHANGED
@@ -1,7 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: Thimblr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.12
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 8
8
+ - 0
9
+ version: 0.8.0
5
10
  platform: ruby
6
11
  authors:
7
12
  - JP Hastings-Spital
@@ -9,29 +14,34 @@ autorequire:
9
14
  bindir: bin
10
15
  cert_chain: []
11
16
 
12
- date: 2010-04-07 00:00:00 +01:00
17
+ date: 2010-04-12 00:00:00 +01:00
13
18
  default_executable: thimblr
14
19
  dependencies:
15
20
  - !ruby/object:Gem::Dependency
16
21
  name: sinatra
17
- type: :runtime
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
20
24
  requirements:
21
25
  - - ">="
22
26
  - !ruby/object:Gem::Version
27
+ segments:
28
+ - 1
29
+ - 0
23
30
  version: "1.0"
24
- version:
31
+ type: :runtime
32
+ version_requirements: *id001
25
33
  - !ruby/object:Gem::Dependency
26
34
  name: launchy
27
- type: :runtime
28
- version_requirement:
29
- version_requirements: !ruby/object:Gem::Requirement
35
+ prerelease: false
36
+ requirement: &id002 !ruby/object:Gem::Requirement
30
37
  requirements:
31
38
  - - ">="
32
39
  - !ruby/object:Gem::Version
40
+ segments:
41
+ - 0
33
42
  version: "0"
34
- version:
43
+ type: :runtime
44
+ version_requirements: *id002
35
45
  description: A webserver built to help you test tumblr themes as you edit them
36
46
  email: jphastings@gmail.com
37
47
  executables:
@@ -43,8 +53,8 @@ extra_rdoc_files: []
43
53
  files:
44
54
  - config/demo.yml
45
55
  - config/settings.default.yaml
46
- - config/settings.yaml
47
56
  - lib/thimblr.rb
57
+ - lib/thimblr/importer.rb
48
58
  - lib/thimblr/parser.rb
49
59
  - public/assets/help.js
50
60
  - public/assets/iphone-style-checkboxes.js
@@ -82,13 +92,14 @@ files:
82
92
  - public/images/slider_center.png
83
93
  - public/images/slider_left.png
84
94
  - public/images/slider_right.png
95
+ - public/index.html
85
96
  - public/stylesheets/help.css
86
97
  - public/stylesheets/tumblr.css
87
98
  - themes/101.html
88
99
  - themes/Redux.html
89
100
  - themes/Stationary.html
90
101
  - views/help.erb
91
- - views/index.erb
102
+ - views/menu.erb
92
103
  has_rdoc: true
93
104
  homepage: http://github.com/jphastings/Thimblr
94
105
  licenses: []
@@ -102,18 +113,20 @@ required_ruby_version: !ruby/object:Gem::Requirement
102
113
  requirements:
103
114
  - - ">="
104
115
  - !ruby/object:Gem::Version
116
+ segments:
117
+ - 0
105
118
  version: "0"
106
- version:
107
119
  required_rubygems_version: !ruby/object:Gem::Requirement
108
120
  requirements:
109
121
  - - ">="
110
122
  - !ruby/object:Gem::Version
123
+ segments:
124
+ - 0
111
125
  version: "0"
112
- version:
113
126
  requirements: []
114
127
 
115
128
  rubyforge_project:
116
- rubygems_version: 1.3.5
129
+ rubygems_version: 1.3.6
117
130
  signing_key:
118
131
  specification_version: 3
119
132
  summary: Helper for Tumblr theme editors
@@ -1,18 +0,0 @@
1
- ## Settings affecting Tumblr
2
- Tumblr:
3
- PostsPerPage: 10
4
-
5
- ## Settings affecting Thimblr
6
- # The location of your theme files
7
- ThemesLocation: themes
8
- # The location of your data files
9
- DataLocation: data
10
-
11
- # This allows the thimblr server to open your chosen editor to edit
12
- # the theme you're currently viewing. There is a (very small!) risk
13
- # that this could do malicious things, so you can disable it if you
14
- # like
15
- AllowEditing: true
16
- # The editor you want to use for editing your themes. Below should
17
- # be what you'd use if you were launching it from the command line
18
- Editor: mate