nanoc-polly 0.0.1.pre1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,15 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
15
+ */public/
data/README.md CHANGED
@@ -1,53 +1,79 @@
1
1
  # Nanoc::Polly
2
2
 
3
- Integrates Pollypost with nanoc.
3
+ ## Integrate Pollypost with nanoc!
4
+
5
+ This Ruby Gem provides a backend for [Pollypost](https://github.com/pollypost/pollypost), so you can use browser based inline editing on static sites generated with [nanoc](http://nanoc.ws/).
4
6
 
5
7
  ## Installation
6
8
 
7
- Add this line to your application's Gemfile:
9
+ Install nanoc-polly yourself as:
10
+
11
+ $ gem install nanoc-polly
12
+
13
+ Or, if you're using [Bundler](http://bundler.io/), add this line to your application's Gemfile:
14
+
15
+ ```ruby
16
+ gem 'nanoc-polly'
17
+ ```
18
+
19
+ And then execute:
20
+
21
+ $ bundle install
22
+
23
+ ### Development version
24
+
25
+ In case you want to use the most up-to-date development version, add this GitHub path to your Gemfile:
8
26
 
9
27
  ```ruby
10
28
  gem 'nanoc-polly', :github => 'pollypost/nanoc-polly'
11
29
  ```
12
- or, if you downloaded the source files to your local file system
30
+ or, if you cloned the source files to your local file system:
13
31
 
14
32
  ```ruby
15
33
  gem 'nanoc-polly', :path => './path_to/nanoc-polly'
16
34
  ```
17
35
 
18
- And then execute:
19
-
20
- $ bundle
36
+ ### Polly Helper
21
37
 
22
- Or download the pkg/nanoc-polly.gem and install it yourself as:
38
+ Nanoc-polly comes with a predefined helper that adds functionality for generating the 'about' tags needed for Pollypost. See [Pollypost](https://github.com/pollypost/pollypost) for details.
23
39
 
24
- $ gem install nanoc-polly.gem
40
+ To activate the helper, add this line to a file in your `lib` folder:
25
41
 
26
- In your nanoc.yaml, add the location of the compiled Pollypost assets folder, e.g.
27
42
  ```ruby
28
- polly:
29
- assets_location: 'pollypost/public/assets'
43
+ include Nanoc::Helpers::Polly
44
+ ```
45
+
46
+ You can then generate a file's 'about' value with `item_about @item`:
47
+
48
+ ```html
49
+ <div class="edit-this" about="<%= item_about @item %>">
50
+ <%= yield %>
51
+ </div>
30
52
  ```
31
53
 
32
54
  ## Usage
33
55
 
34
- To enable Pollypost on your site, just start the nanoc weserver with
56
+ To enable Pollypost on your site, just start the nanoc webserver with
35
57
 
36
58
  $ nanoc edit -a
37
59
 
38
- This behaves very similar to `nanoc view` but adds all the components needed for Pollypost. The -a Option loads all the assets shipped with Pollypost, without it you'd have to make sure yourself that the files are found on the specified path.
60
+ This behaves very similar to `nanoc view` but adds all the components needed for Pollypost. The `-a` Option loads all the assets shipped with Pollypost, without it you'd have to make sure yourself that the files are found on the specified path (see Config Options).
61
+
62
+ Your site is available at `localhost:3000`.
63
+
64
+ For additional options try `nanoc edit --help`.
39
65
 
40
66
  ## Config Options
41
67
 
42
- In your nanoc.yaml file you can set the following configuration options:
68
+ In your nanoc.yaml file you can set the following configuration options for Pollypost (shown here are their default values):
43
69
 
44
70
  ```ruby
45
71
  polly:
46
- assets_location: 'nocms/pollypost/public/assets'
47
- assets_path_prefix: '/polly/assets/'
48
- backend_path_prefix: '/polly/'
49
- image_storage: uploadcare
50
- uploadcare_api_key: 82f609e341c7fe23fcc6
72
+ assets_location: 'public/polly' # folder where the compiled Pollypost assets are stored
73
+ assets_path_prefix: '/polly/assets/' # url prefix for Pollypost asset paths
74
+ backend_path_prefix: '/polly/' # url prefix for Pollypost backend paths
75
+ image_storage: '' # which image storage to use (e.g. 'uploadcare')
76
+ uploadcare_api_key: '' # api key if you are using uploadcare as image storage
51
77
  ```
52
78
 
53
79
  ## Contributing
@@ -58,3 +84,13 @@ polly:
58
84
  4. Push to the branch (`git push origin my-new-feature`)
59
85
  5. Create a new Pull Request
60
86
 
87
+
88
+ ## License
89
+
90
+ Copyright (C) 2015 [more onion](https://www.more-onion.com)
91
+
92
+ Pollypost is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
93
+
94
+ Pollypost is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
95
+
96
+ You should have received a copy of the GNU General Public License (LICENSE.md) along with this program. If not, see <http://www.gnu.org/licenses/>.
data/Rakefile CHANGED
@@ -1,3 +1,2 @@
1
1
  require "bundler/gem_tasks"
2
- require "pollypost/asset_tasks"
3
2
 
data/lib/nanoc-edit.rb CHANGED
@@ -22,12 +22,20 @@ option :i, :host, 'host to use (default: 0.0.0.0)', :argument => :optional
22
22
 
23
23
  module Nanoc::CLI::Commands
24
24
  class Edit < ::Nanoc::CLI::CommandRunner
25
+ DEFAULT_DATA_SOURCE_INDEX = 0
25
26
  DEFAULT_HANDLER_NAME = :thin
26
27
  DEFAULT_BACKEND_PATH_PREFIX = '/polly/'
27
28
  DEFAULT_ASSETS_PATH_PREFIX = '/polly/assets/'
29
+ DEFAULT_ASSETS_LOCATION = 'public/polly/'
28
30
 
29
31
  def run
30
- require_site
32
+ # require_site
33
+ site = nil
34
+ if Nanoc::Site.cwd_is_nanoc_site?
35
+ site = Nanoc::Site.new('.')
36
+ else
37
+ raise ::Nanoc::Errors::GenericTrivial, 'The current working directory does not seem to be a nanoc site.'
38
+ end
31
39
 
32
40
  require 'rack'
33
41
  require 'rack/polly'
@@ -44,9 +52,11 @@ module Nanoc::CLI::Commands
44
52
  end
45
53
  end
46
54
 
55
+ polly_config = site.config[:polly] ? site.config[:polly] : {}
47
56
  with_assets = options[:assets] ? true : false
48
- if with_assets
49
- raise ArgumentError, "assets_location not configured" unless site.config[:polly][:assets_location]
57
+ assets_location = polly_config[:assets_location] ? polly_config[:assets_location] : DEFAULT_ASSETS_LOCATION
58
+ if with_assets && !File.directory?(File.expand_path(assets_location))
59
+ raise ArgumentError, "assets_location '#{assets_location}' is not a directory."
50
60
  end
51
61
 
52
62
  # Set options
@@ -56,32 +66,32 @@ module Nanoc::CLI::Commands
56
66
  }
57
67
 
58
68
  # Build app
59
- site = self.site
60
69
  require 'nanoc/polly/backend'
61
70
 
62
71
  rack_polly_options = {}
63
72
 
64
73
  # set required options
65
- backend_path_prefix = site.config[:polly][:backend_path_prefix] ? site.config[:polly][:backend_path_prefix] : DEFAULT_BACKEND_PATH_PREFIX
66
- assets_path_prefix = site.config[:polly][:assets_path_prefix] ? site.config[:polly][:assets_path_prefix] : DEFAULT_ASSETS_PATH_PREFIX
74
+ data_source_index = polly_config[:data_source_index] ? polly_config[:data_source_index] : DEFAULT_DATA_SOURCE_INDEX
75
+ backend_path_prefix = polly_config[:backend_path_prefix] ? polly_config[:backend_path_prefix] : DEFAULT_BACKEND_PATH_PREFIX
76
+ assets_path_prefix = polly_config[:assets_path_prefix] ? polly_config[:assets_path_prefix] : DEFAULT_ASSETS_PATH_PREFIX
67
77
  rack_polly_options = rack_polly_options.merge({
68
78
  assets_path_prefix: assets_path_prefix,
69
79
  backend_path_prefix: backend_path_prefix
70
80
  })
71
81
 
72
82
  # set image storage options
73
- image_storage = site.config[:polly][:image_storage] ? site.config[:polly][:image_storage] : false
83
+ image_storage = polly_config[:image_storage] ? polly_config[:image_storage] : false
74
84
  if image_storage && image_storage.to_s == 'uploadcare'
75
- raise ArgumentError, "uploadcare_api_key not configured" unless site.config[:polly][:uploadcare_api_key]
85
+ raise ArgumentError, "uploadcare_api_key not configured" unless polly_config[:uploadcare_api_key]
76
86
  rack_polly_options = rack_polly_options.merge({
77
87
  image_storage: image_storage,
78
- uploadcare_api_key: site.config[:polly][:uploadcare_api_key]
88
+ uploadcare_api_key: polly_config[:uploadcare_api_key]
79
89
  })
80
90
  end
81
91
 
82
92
  app = Rack::Builder.new do
83
93
  map assets_path_prefix do
84
- run Rack::File.new(site.config[:polly][:assets_location])
94
+ run Rack::File.new(assets_location)
85
95
  end if with_assets
86
96
  map '/' do
87
97
  use Rack::CommonLogger
@@ -93,7 +103,8 @@ module Nanoc::CLI::Commands
93
103
  run Rack::File.new(site.config[:output_dir])
94
104
  end
95
105
  map backend_path_prefix do
96
- run Nanoc::Polly::Backend.new
106
+ Nanoc::Polly::Config.data_source_index = data_source_index
107
+ run Nanoc::Polly::Backend.new
97
108
  end
98
109
  end.to_app
99
110
 
@@ -0,0 +1,21 @@
1
+ # Copyright (C) 2015 more onion
2
+ #
3
+ # Pollypost is free software: you can use, redistribute and/or modify it
4
+ # under the terms of the GNU General Public License version 3 or later.
5
+ # See LICENCE.txt or <http://www.gnu.org/licenses/> for more details.
6
+
7
+
8
+ module Nanoc::Helpers
9
+ module Polly
10
+ def item_about item
11
+ if item[:about]
12
+ item[:about]
13
+ elsif item.path == '/' # special path
14
+ 'index'
15
+ else
16
+ # remove leading and trailing /
17
+ item.path.sub(/\A\//,'').sub(/\/\z/, '')
18
+ end
19
+ end
20
+ end
21
+ end
data/lib/nanoc/polly.rb CHANGED
@@ -7,6 +7,7 @@
7
7
 
8
8
 
9
9
  require "nanoc/polly/version"
10
+ require "nanoc/helpers/polly"
10
11
  require 'nanoc'
11
12
  require 'nanoc/cli'
12
13
  require 'nanoc/cli/command_runner'
@@ -11,6 +11,7 @@ require 'json'
11
11
  require 'nanoc'
12
12
  require 'loofah'
13
13
  require 'htmlbeautifier'
14
+ require 'nanoc/polly/config'
14
15
 
15
16
  module Nanoc::Polly
16
17
  class Backend < Sinatra::Base
@@ -41,29 +42,18 @@ class Backend < Sinatra::Base
41
42
  end
42
43
 
43
44
  if identifier && json['content']
44
- require_site
45
-
46
45
  # TODO find a way to not have to load the site twice in one request
47
- site = Nanoc::Site.new('.')
48
- data_source = Nanoc::DataSources::FilesystemUnified.new(site, '/', '/', {})
49
- if site.items[identifier]
46
+ # assuming we are running in a nanoc site dir
47
+ @site = Nanoc::Site.new('.')
48
+ @data_source = @site.data_sources[Nanoc::Polly::Config.data_source_index]
49
+ if @site.items[identifier]
50
50
  return [409, {}, {
51
51
  about: identifier,
52
52
  message: "Page already exists."
53
53
  }.to_json ]
54
54
  end
55
55
 
56
- sanitized_content = sanitize_content(json['content'])
57
- data_source.create_item(sanitized_content, {
58
- about: about,
59
- title: json['title'] ? json['title'] : 'Title',
60
- layout: 'default'}, identifier)
61
- recompile!
62
- return [ 202, {}, {
63
- about: identifier,
64
- message: "Page creation request accepted.",
65
- content: sanitized_content
66
- }.to_json ]
56
+ create! identifier, about, json
67
57
  else
68
58
  return [400, {}, {
69
59
  message: "Invalid request."
@@ -86,9 +76,9 @@ class Backend < Sinatra::Base
86
76
  end
87
77
  identifier = '/' + about + '/'
88
78
  end
89
-
90
- require_site
79
+
91
80
  # TODO find a way to not have to load the site twice in one request
81
+ # assuming we are running in a nanoc site dir
92
82
  site = Nanoc::Site.new('.')
93
83
  if site.items[identifier]
94
84
  return [200, {}, {
@@ -120,14 +110,13 @@ class Backend < Sinatra::Base
120
110
  identifier = '/' + about + '/'
121
111
  end
122
112
 
123
-
124
- require_site
125
113
  # TODO find a way to not have to load the site twice in one request
126
- site = Nanoc::Site.new('.')
127
- data_source = Nanoc::DataSources::FilesystemUnified.new(site, '/', '/', {})
114
+ # assuming we are running in a nanoc site dir
115
+ @site = Nanoc::Site.new('.')
116
+ @data_source = @site.data_sources[Nanoc::Polly::Config.data_source_index]
128
117
  attributes = []
129
118
  # read and use attributes from saved item
130
- if item = site.items[identifier]
119
+ if item = @site.items[identifier]
131
120
  attributes = sanitize_attributes(item.attributes)
132
121
  else
133
122
  return [404, {}, {
@@ -136,21 +125,12 @@ class Backend < Sinatra::Base
136
125
  }.to_json ]
137
126
  end
138
127
 
128
+ @content_bak = item.raw_content.clone
129
+ @attributes_bak = item.attributes.clone
139
130
  body = request.body.read
140
131
  json = JSON.parse(body)
141
132
  if json['content']
142
- sanitized_content = sanitize_content(json['content'])
143
- attributes.merge!(json['attributes']) if json['attributes']
144
- # make sure that about is not overriden in PUT
145
- # we always want this to be the value given in the request path
146
- attributes[:about] = about
147
- data_source.create_item(sanitized_content, attributes, identifier)
148
- recompile!
149
- return [ 202, {}, {
150
- about: identifier,
151
- message: "Page update request accepted.",
152
- content: sanitized_content
153
- }.to_json ]
133
+ update! identifier, about, attributes, json
154
134
  else
155
135
  return [400, {}, {
156
136
  message: "Invalid request."
@@ -173,6 +153,8 @@ class Backend < Sinatra::Base
173
153
  }.to_json]
174
154
  end
175
155
 
156
+ protected
157
+
176
158
  # @TODO
177
159
  def sanitize_about about
178
160
  return about
@@ -194,13 +176,73 @@ class Backend < Sinatra::Base
194
176
 
195
177
  # TODO maybe as a nonblocking background task
196
178
  def recompile!
197
- require_site
198
179
  # difficult to cache site because of nanoc internal caching (freeze)
199
180
  # TODO optimize recompilation
181
+ # assuming we are running in a nanoc site dir
200
182
  site = Nanoc::Site.new('.')
201
183
  site.compile
202
184
  end
203
185
 
186
+ def create! identifier, about, json
187
+ sanitized_content = sanitize_content(json['content'])
188
+ begin
189
+ @data_source.create_item(sanitized_content, {
190
+ about: about,
191
+ title: json['title'] ? json['title'] : 'Title',
192
+ layout: 'default'}, identifier)
193
+ recompile!
194
+ rescue Nanoc::Errors::Generic => e
195
+ # rollback, i.e. delete the newly created file
196
+ # we assume the file was created in this request as we should have
197
+ # passed the "page already exists" test in the post handler
198
+ new_items = @data_source.items.select do |item|
199
+ item.identifier == identifier
200
+ end
201
+ path = File.expand_path(new_items.first.raw_filename)
202
+ if File.file? path
203
+ File.delete path
204
+ end
205
+ puts "[ERR] #{e}"
206
+ recompile!
207
+ return [ 400, {}, {
208
+ about: identifier,
209
+ message: "Invalid request. #{e} Rolled back."
210
+ }.to_json ]
211
+ end
212
+
213
+ return [ 202, {}, {
214
+ about: identifier,
215
+ message: "Page creation request accepted.",
216
+ content: sanitized_content
217
+ }.to_json ]
218
+ end
219
+
220
+ def update! identifier, about, attributes, json
221
+ sanitized_content = sanitize_content(json['content'])
222
+ attributes.merge!(json['attributes']) if json['attributes']
223
+ # make sure that about is not overriden in PUT
224
+ # we always want this to be the value given in the request path
225
+ attributes[:about] = about
226
+ begin
227
+ @data_source.create_item(sanitized_content, attributes, identifier)
228
+ recompile!
229
+ rescue Nanoc::Errors::Generic => e
230
+ @data_source.create_item(@content_bak, @attributes_bak, identifier)
231
+ recompile!
232
+ puts "[ERR] #{e}"
233
+ return [ 400, {}, {
234
+ about: identifier,
235
+ message: "Invalid request. #{e} Rolled back."
236
+ }.to_json ]
237
+ end
238
+
239
+ return [ 202, {}, {
240
+ about: identifier,
241
+ message: "Page update request accepted.",
242
+ content: sanitized_content
243
+ }.to_json ]
244
+ end
245
+
204
246
  # start the server if ruby file executed directly
205
247
  run! if app_file == $0
206
248
  end
@@ -0,0 +1,19 @@
1
+ # This file is part of nanoc-polly, a nanoc backend for Pollypost.
2
+ # Copyright (C) 2015 more onion
3
+ #
4
+ # Pollypost is free software: you can use, redistribute and/or modify it
5
+ # under the terms of the GNU General Public License version 3 or later.
6
+ # See LICENCE.txt or <http://www.gnu.org/licenses/> for more details.
7
+
8
+
9
+ module Nanoc::Polly
10
+ class Config
11
+ class << self
12
+ attr_accessor :data_source_index
13
+ end
14
+
15
+ def self.data_source_index
16
+ @data_source_index || 0
17
+ end
18
+ end
19
+ end
@@ -8,6 +8,6 @@
8
8
 
9
9
  module Nanoc
10
10
  module Polly
11
- VERSION = "0.0.1.pre1"
11
+ VERSION = "0.0.2"
12
12
  end
13
13
  end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nanoc-polly
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1.pre1
5
- prerelease: 6
4
+ version: 0.0.2
5
+ prerelease:
6
6
  platform: ruby
7
7
  authors:
8
8
  - Alex Berger
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-04-13 00:00:00.000000000 Z
12
+ date: 2015-04-16 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: nanoc
@@ -130,13 +130,16 @@ executables: []
130
130
  extensions: []
131
131
  extra_rdoc_files: []
132
132
  files:
133
+ - .gitignore
133
134
  - Gemfile
134
135
  - LICENSE.txt
135
136
  - README.md
136
137
  - Rakefile
137
138
  - lib/nanoc-edit.rb
139
+ - lib/nanoc/helpers/polly.rb
138
140
  - lib/nanoc/polly.rb
139
141
  - lib/nanoc/polly/backend.rb
142
+ - lib/nanoc/polly/config.rb
140
143
  - lib/nanoc/polly/version.rb
141
144
  - lib/rack/polly.rb
142
145
  - nanoc-polly.gemspec
@@ -156,9 +159,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
156
159
  required_rubygems_version: !ruby/object:Gem::Requirement
157
160
  none: false
158
161
  requirements:
159
- - - ! '>'
162
+ - - ! '>='
160
163
  - !ruby/object:Gem::Version
161
- version: 1.3.1
164
+ version: '0'
162
165
  requirements: []
163
166
  rubyforge_project:
164
167
  rubygems_version: 1.8.23