nanoc-polly 0.0.1.pre1 → 0.0.2

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/.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