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 +15 -0
- data/README.md +55 -19
- data/Rakefile +0 -1
- data/lib/nanoc-edit.rb +22 -11
- data/lib/nanoc/helpers/polly.rb +21 -0
- data/lib/nanoc/polly.rb +1 -0
- data/lib/nanoc/polly/backend.rb +78 -36
- data/lib/nanoc/polly/config.rb +19 -0
- data/lib/nanoc/polly/version.rb +1 -1
- metadata +8 -5
data/.gitignore
ADDED
data/README.md
CHANGED
@@ -1,53 +1,79 @@
|
|
1
1
|
# Nanoc::Polly
|
2
2
|
|
3
|
-
|
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
|
-
|
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
|
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
|
-
|
19
|
-
|
20
|
-
$ bundle
|
36
|
+
### Polly Helper
|
21
37
|
|
22
|
-
|
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
|
-
|
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
|
-
|
29
|
-
|
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
|
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
|
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: '
|
47
|
-
assets_path_prefix: '/polly/assets/'
|
48
|
-
backend_path_prefix: '/polly/'
|
49
|
-
image_storage: uploadcare
|
50
|
-
uploadcare_api_key:
|
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
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
|
-
|
49
|
-
|
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
|
-
|
66
|
-
|
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 =
|
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
|
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:
|
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(
|
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
|
-
|
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
data/lib/nanoc/polly/backend.rb
CHANGED
@@ -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
|
48
|
-
|
49
|
-
|
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
|
-
|
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
|
127
|
-
|
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
|
-
|
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
|
data/lib/nanoc/polly/version.rb
CHANGED
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.
|
5
|
-
prerelease:
|
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-
|
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:
|
164
|
+
version: '0'
|
162
165
|
requirements: []
|
163
166
|
rubyforge_project:
|
164
167
|
rubygems_version: 1.8.23
|