copy 0.0.41 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,8 +1,67 @@
1
- ## Copy is a sinatra-based content management system.
1
+ # Copy is a simple, Sinatra-based content management system.
2
2
 
3
- Copy is similar to [Brochure](https://github.com/sstephenson/brochure) in spirit, but with the addition of editable text blocks.
3
+ `$ gem install copy` and then generate a new site `$ copy -n mynewsite`
4
4
 
5
- More soon.
5
+ mynewsite/
6
+ ├── Gemfile <- Uncomment the gems you need for storage.
7
+ ├── config.ru <- Configure storage, user, and password here.
8
+ ├── public <- The public root of your new site.
9
+ │   ├── favicon.ico Ships with a few helpful defaults.
10
+ │   ├── images
11
+ │   ├── javascripts
12
+ │   │   └── main.js
13
+ │   ├── robots.txt
14
+ │   └── stylesheets
15
+ │   └── main.css
16
+ └── views <- Your views, layouts, and partials live here.
17
+ ├── index.html.erb
18
+ └── layout.html.erb
19
+
20
+ The layout (`layout.html.erb`) yields to all the views. It's not required so delete it if your views contain full html documents.
21
+
22
+ Copy automatically maps URLs to files in your `views` directory.
23
+
24
+ * `/` &rarr; `index.html.erb`
25
+ * `/about` &rarr; `about.html.erb` or `about/index.html.erb`
26
+ * `/about/us` &rarr; `about/us.html.erb`
27
+
28
+ Copy lets you define blocks of editable text in your views.
29
+
30
+ <% copy :contact do %>
31
+ 1 _Infinite_ Loop
32
+ Cupertino, CA 95014
33
+ 408.996.1010
34
+ <% end %>
35
+
36
+ The text provided in the block will be saved and can then be edited live on the site. All content is formatted with Markdown. [See demo](http://copy-demo.heroku.com) for a live example or [view the source](https://github.com/javan/copy-demo).
37
+
38
+ Single line blocks will be edited in a text field as opposed to a textarea. Perfect for headlines.
39
+
40
+ <h1><% copy :title %>Like a boss!<% end %></h1>
41
+
42
+ **Partials** can be rendered from any view with the `partial` helper. Their filenames are always prefixed with an underscore.
43
+
44
+ * `<%= partial 'nav' %>` renders `_nav.html.erb`
45
+ * `<%= partial 'shared/details' %>` renders `shared/_details.html.erb`
46
+
47
+ ----
48
+
49
+ ### Storage
50
+
51
+ Copy supports multiple backends for storage: redis, mongodb, mysql, postgres, and sqlite.
52
+
53
+ Choosing and configuring your storage option is done in one line in your `config.ru` file by providing a connection URI.
54
+
55
+ Examples:
56
+
57
+ * `set :storage, 'mongodb://user:pass@host:port/database'`
58
+ * `set :storage, 'postgres://user:pass@host/database'`
59
+
60
+ ----
61
+
62
+ ### Editing copy on your live site
63
+
64
+ Browse to `/_copy` and drag the "Edit Copy" link to your bookmarks bar. Return to your site, click the bookmark (you'll be prompted for your username and password) and then click on the highlighted text to edit it. That's it!
6
65
 
7
66
  ----
8
67
 
data/copy.gemspec CHANGED
@@ -8,9 +8,9 @@ Gem::Specification.new do |s|
8
8
  s.platform = Gem::Platform::RUBY
9
9
  s.authors = ["Javan Makhmali"]
10
10
  s.email = ["javan@javan.us"]
11
- s.homepage = ""
12
- s.summary = %q{Tiny CMS built with Sinatra}
13
- s.description = %q{Serve mostly static pages with blocks of client-editable text.}
11
+ s.homepage = "https://github.com/javan/copy"
12
+ s.summary = %q{Simple, Sinatra-based CMS.}
13
+ s.description = %q{Serves mostly static pages with blocks of editable copy.}
14
14
 
15
15
  s.rubyforge_project = "copy"
16
16
 
@@ -48,9 +48,13 @@
48
48
  text-decoration: underline;
49
49
  }
50
50
 
51
- #_copy textarea {
51
+ #_copy textarea,
52
+ #_copy input[type="text"] {
52
53
  font-size: 13px;
53
- height: 300px;
54
54
  width: 490px;
55
55
  padding: 5px;
56
+ }
57
+
58
+ #_copy textarea {
59
+ height: 300px;
56
60
  }
@@ -1,6 +1,10 @@
1
1
  <div id="_copy">
2
2
  <form class="_copy_edit_form" data-content-name="<%= @name %>" action="/_copy/<%= @name %>">
3
- <textarea name="content"><%= @doc %></textarea>
3
+ <% if @doc =~ /\n/ %>
4
+ <textarea name="content"><%=h @doc %></textarea>
5
+ <% else %>
6
+ <input type="text" name="content" value="<%=h @doc %>" />
7
+ <% end %>
4
8
  <p class="_copy_footer _copy_footer_left">
5
9
  <input class="_copy_submit" type="submit" value="Save" />
6
10
  or <a class="_copy_cancel" href="#">cancel</a>
@@ -31,7 +31,7 @@ jQuery.noConflict();
31
31
  success: function(html) {
32
32
  $('body').prepend(html);
33
33
  $('#_copy').css({ margin:'-'+($('#_copy').height() / 2)+'px 0 0 -'+($('#_copy').width() / 2)+'px' });
34
- $('#_copy textarea').get(0).focus();
34
+ $('#_copy [name="content"]').get(0).focus();
35
35
  }
36
36
  });
37
37
  });
@@ -39,6 +39,7 @@ jQuery.noConflict();
39
39
  $('._copy_cancel').live('click', function() {
40
40
  $('#_copy').remove();
41
41
  clickable();
42
+ return false;
42
43
  });
43
44
 
44
45
  $('._copy_edit_form').live('submit', function() {
@@ -48,7 +49,7 @@ jQuery.noConflict();
48
49
  $.ajax({
49
50
  type: 'PUT',
50
51
  url: form.attr('action'),
51
- data: { content: form.find('textarea').val(), wrap_tag: original.get(0).tagName.toLowerCase() },
52
+ data: { content: form.find('[name="content"]').val(), wrap_tag: original.get(0).tagName.toLowerCase() },
52
53
  success: function(html) {
53
54
  $('#_copy').remove();
54
55
  original.replaceWith(html);
@@ -1,9 +1,6 @@
1
- begin
2
- require 'copy'
3
- rescue LoadError
4
- require 'rubygems'
5
- require 'copy'
6
- end
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ Bundler.require(:default)
7
4
 
8
5
  Copy::Server.config do
9
6
  # Sets a Cache-Control header for the duration specified.
@@ -20,6 +17,7 @@ Copy::Server.config do
20
17
  # set :copy_password, ENV['COPY_PASSWORD']
21
18
 
22
19
  # Enter the URL to your data store.
20
+ # Be sure to uncomment the correlating gems in your Gemfile.
23
21
  # "redis://", "mongodb://", "mysql://", "postgres://", and "sqlite://" are supported.
24
22
  # Heroku friendly: http://devcenter.heroku.com/articles/mongohq
25
23
  #
@@ -4,9 +4,11 @@
4
4
  <meta charset="utf-8">
5
5
  <title>I love Copy</title>
6
6
  <link rel="stylesheet" href="/stylesheets/main.css">
7
- <script src="/javascripts/main.js"></script>
8
7
  </head>
9
8
  <body>
9
+
10
10
  <%= yield %>
11
+
12
+ <script src="/javascripts/main.js"></script>
11
13
  </body>
12
14
  </html>
data/lib/copy/server.rb CHANGED
@@ -9,6 +9,9 @@ module Copy
9
9
  set :root, File.dirname(File.expand_path(__FILE__))
10
10
 
11
11
  helpers do
12
+ include Rack::Utils
13
+ alias_method :h, :escape_html
14
+
12
15
  def protected!
13
16
  unless authorized?
14
17
  response['WWW-Authenticate'] = %(Basic realm="Copy Admin Area")
@@ -68,6 +71,12 @@ module Copy
68
71
  # Append the output buffer.
69
72
  @_out_buf << format_text(name, content, options)
70
73
  end
74
+
75
+ def partial(template)
76
+ template_array = template.to_s.split('/')
77
+ template = template_array[0..-2].join('/') + "/_#{template_array[-1]}.#{@_route.format}"
78
+ send(@_route.renderer, template.to_sym, :layout => false)
79
+ end
71
80
  end
72
81
 
73
82
  def self.config(&block)
@@ -105,11 +114,11 @@ module Copy
105
114
  end
106
115
 
107
116
  get '*' do
108
- route = Copy::Router.new(params[:splat].first, settings.views)
109
- if route.success?
117
+ @_route = Copy::Router.new(params[:splat].first, settings.views)
118
+ if @_route.success?
110
119
  set_cache_control_header
111
- content_type(route.format)
112
- send(route.renderer, route.template, :layout => route.layout)
120
+ content_type(@_route.format)
121
+ send(@_route.renderer, @_route.template, :layout => @_route.layout)
113
122
  else
114
123
  not_found
115
124
  end
@@ -1,4 +1,3 @@
1
- require 'mongo'
2
1
  require 'uri'
3
2
 
4
3
  module Copy
@@ -1,5 +1,3 @@
1
- require 'redis'
2
-
3
1
  module Copy
4
2
  module Storage
5
3
  class Redis
@@ -16,4 +14,4 @@ module Copy
16
14
  end
17
15
  end
18
16
  end
19
- end
17
+ end
@@ -1,5 +1,3 @@
1
- require 'data_mapper'
2
-
3
1
  module Copy
4
2
  module Storage
5
3
  class Relational
data/lib/copy/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Copy
2
- VERSION = '0.0.41'
2
+ VERSION = '0.1.0'
3
3
  end
data/test/server_test.rb CHANGED
@@ -112,6 +112,12 @@ class ServerCopyHelperTest < Test::Unit::TestCase
112
112
  assert last_response.ok?
113
113
  assert_match %Q(<span class="_copy_editable" data-name="headline">Important!</span>), last_response.body
114
114
  end
115
+
116
+ test "partial rendering" do
117
+ get 'renders_partials'
118
+ assert last_response.ok?, last_response.errors
119
+ assert_match "before\none\ntwo\nthree\nafter", last_response.body
120
+ end
115
121
  end
116
122
 
117
123
  class ServerAdminTest < Test::Unit::TestCase
@@ -146,12 +152,18 @@ class ServerAdminTest < Test::Unit::TestCase
146
152
 
147
153
  test "GET /_copy/:name" do
148
154
  Copy::Storage.stubs(:connected?).returns(true)
149
- Copy::Storage.expects(:get).with('fun').returns('party')
155
+ Copy::Storage.expects(:get).with('fun').returns('"party"')
150
156
 
151
157
  authorize!
152
158
  get '/_copy/fun'
153
159
  assert last_response.ok?, last_response.errors
154
- assert_match "party</textarea>", last_response.body
160
+ # Single line content renders in a text field
161
+ assert_match 'value="&quot;party&quot;"', last_response.body
162
+
163
+ # Multiline renders in a textarea
164
+ Copy::Storage.expects(:get).with('fun').returns("<b>party\n")
165
+ get '/_copy/fun'
166
+ assert_match "&lt;b&gt;party\n</textarea>", last_response.body
155
167
  end
156
168
 
157
169
  test "PUT /_copy/:name" do
@@ -0,0 +1 @@
1
+ one
@@ -0,0 +1 @@
1
+ three
@@ -0,0 +1,2 @@
1
+ two
2
+ <%= partial :three %>
@@ -0,0 +1,4 @@
1
+ before
2
+ <%= partial 'one' %>
3
+ <%= partial 'about/two' %>
4
+ after
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: copy
3
3
  version: !ruby/object:Gem::Version
4
- hash: 77
4
+ hash: 27
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
+ - 1
8
9
  - 0
9
- - 41
10
- version: 0.0.41
10
+ version: 0.1.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Javan Makhmali
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-05-15 00:00:00 -04:00
18
+ date: 2011-05-19 00:00:00 -04:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -62,7 +62,7 @@ dependencies:
62
62
  version: "0"
63
63
  type: :development
64
64
  version_requirements: *id003
65
- description: Serve mostly static pages with blocks of client-editable text.
65
+ description: Serves mostly static pages with blocks of editable copy.
66
66
  email:
67
67
  - javan@javan.us
68
68
  executables:
@@ -106,17 +106,21 @@ files:
106
106
  - test/router_test.rb
107
107
  - test/server_test.rb
108
108
  - test/storage_test.rb
109
+ - test/test_app/views/_one.html.erb
110
+ - test/test_app/views/_three.html.erb
111
+ - test/test_app/views/about/_two.html.erb
109
112
  - test/test_app/views/about/index.html.erb
110
113
  - test/test_app/views/about/us.html.erb
111
114
  - test/test_app/views/data/people.csv.erb
112
115
  - test/test_app/views/data/people.xml.erb
113
116
  - test/test_app/views/index.html.erb
114
117
  - test/test_app/views/layout.html.erb
118
+ - test/test_app/views/renders_partials.html.erb
115
119
  - test/test_app/views/with_copy_helper.html.erb
116
120
  - test/test_app/views/with_copy_helper_one_line.html.erb
117
121
  - test/test_helper.rb
118
122
  has_rdoc: true
119
- homepage: ""
123
+ homepage: https://github.com/javan/copy
120
124
  licenses: []
121
125
 
122
126
  post_install_message:
@@ -148,17 +152,21 @@ rubyforge_project: copy
148
152
  rubygems_version: 1.4.2
149
153
  signing_key:
150
154
  specification_version: 3
151
- summary: Tiny CMS built with Sinatra
155
+ summary: Simple, Sinatra-based CMS.
152
156
  test_files:
153
157
  - test/router_test.rb
154
158
  - test/server_test.rb
155
159
  - test/storage_test.rb
160
+ - test/test_app/views/_one.html.erb
161
+ - test/test_app/views/_three.html.erb
162
+ - test/test_app/views/about/_two.html.erb
156
163
  - test/test_app/views/about/index.html.erb
157
164
  - test/test_app/views/about/us.html.erb
158
165
  - test/test_app/views/data/people.csv.erb
159
166
  - test/test_app/views/data/people.xml.erb
160
167
  - test/test_app/views/index.html.erb
161
168
  - test/test_app/views/layout.html.erb
169
+ - test/test_app/views/renders_partials.html.erb
162
170
  - test/test_app/views/with_copy_helper.html.erb
163
171
  - test/test_app/views/with_copy_helper_one_line.html.erb
164
172
  - test/test_helper.rb