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 +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
|