cloudpress 0.1.0
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.
- checksums.yaml +7 -0
- data/.gitignore +10 -0
- data/.travis.yml +3 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +39 -0
- data/Rakefile +30 -0
- data/app/assets/cloudpress/cloudpress.css.sass +1 -0
- data/app/assets/cloudpress/code/railscasts.css +70 -0
- data/app/controllers/cloudpress/application_controller.rb +12 -0
- data/app/controllers/cloudpress/archives_controller.rb +34 -0
- data/app/controllers/cloudpress/posts_controller.rb +23 -0
- data/app/controllers/cloudpress/tags_controller.rb +20 -0
- data/app/helpers/cloudpress/renderer_helper.rb +23 -0
- data/app/jobs/cloudpress/update_posts_job.rb +9 -0
- data/app/models/cloudpress/archive.rb +50 -0
- data/app/models/cloudpress/post.rb +65 -0
- data/app/views/cloudpress/archives/_archive.html.slim +3 -0
- data/app/views/cloudpress/archives/_archives.html.slim +2 -0
- data/app/views/cloudpress/archives/_month.html.slim +2 -0
- data/app/views/cloudpress/archives/show.html.slim +1 -0
- data/app/views/cloudpress/posts/_intro.html.slim +9 -0
- data/app/views/cloudpress/posts/_post.html.slim +8 -0
- data/app/views/cloudpress/posts/index.html.slim +1 -0
- data/app/views/cloudpress/posts/show.html.slim +1 -0
- data/app/views/cloudpress/tags/_tag.html.slim +2 -0
- data/app/views/cloudpress/tags/_tags.html.slim +2 -0
- data/app/views/cloudpress/tags/show.html.slim +1 -0
- data/bin/console +14 -0
- data/bin/rails +12 -0
- data/bin/setup +7 -0
- data/cloudpress.gemspec +35 -0
- data/config/initializers/tag_extensions.rb +4 -0
- data/config/routes.rb +9 -0
- data/db/migrate/20150309115639_create_cloudpress_posts.rb +19 -0
- data/db/migrate/20150315192521_create_tags_table.rb +30 -0
- data/db/migrate/20150315193206_create_friendly_id_slugs.rb +15 -0
- data/db/migrate/20150317121651_add_slug_to_tags.rb +6 -0
- data/db/migrate/20150317122608_add_taggings_counter_cache.rb +14 -0
- data/lib/cloudpress.rb +105 -0
- data/lib/cloudpress/dropbox/cleaner.rb +20 -0
- data/lib/cloudpress/dropbox/client.rb +15 -0
- data/lib/cloudpress/dropbox/connector.rb +24 -0
- data/lib/cloudpress/dropbox/directory.rb +57 -0
- data/lib/cloudpress/dropbox/file.rb +57 -0
- data/lib/cloudpress/engine.rb +10 -0
- data/lib/cloudpress/formatters/html_with_pygments.rb +7 -0
- data/lib/cloudpress/renderers/archive.rb +18 -0
- data/lib/cloudpress/renderers/archives.rb +24 -0
- data/lib/cloudpress/renderers/post.rb +39 -0
- data/lib/cloudpress/renderers/posts.rb +38 -0
- data/lib/cloudpress/renderers/tag.rb +18 -0
- data/lib/cloudpress/renderers/tags.rb +24 -0
- data/lib/cloudpress/version.rb +3 -0
- data/lib/generators/cloudpress/initializer/USAGE +8 -0
- data/lib/generators/cloudpress/initializer/initializer_generator.rb +32 -0
- metadata +283 -0
@@ -0,0 +1 @@
|
|
1
|
+
= render_cloudpress_posts(posts)
|
@@ -0,0 +1,9 @@
|
|
1
|
+
article id="post-#{renderer.post.id}"
|
2
|
+
header
|
3
|
+
h1 = link_to renderer.post.title, post_path(renderer.post)
|
4
|
+
time = renderer.post.publish_date.to_s(:long)
|
5
|
+
= render_cloudpress_tags(renderer.post.tags) if renderer.tags?
|
6
|
+
p
|
7
|
+
= renderer.post.summary
|
8
|
+
footer
|
9
|
+
= link_to 'Read more', post_path(renderer.post)
|
@@ -0,0 +1 @@
|
|
1
|
+
= render_cloudpress_posts(posts)
|
@@ -0,0 +1 @@
|
|
1
|
+
= render_cloudpress_post(post)
|
@@ -0,0 +1 @@
|
|
1
|
+
= render_cloudpress_posts(posts)
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "cloudpress"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/rails
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# This command will automatically be run when you run "rails" with Rails 4 gems installed from the root of your application.
|
3
|
+
|
4
|
+
ENGINE_ROOT = File.expand_path('../..', __FILE__)
|
5
|
+
ENGINE_PATH = File.expand_path('../../lib/cloudpress/engine', __FILE__)
|
6
|
+
|
7
|
+
# Set up gems listed in the Gemfile.
|
8
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
|
9
|
+
require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
|
10
|
+
|
11
|
+
require 'rails/all'
|
12
|
+
require 'rails/engine/commands'
|
data/bin/setup
ADDED
data/cloudpress.gemspec
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'cloudpress/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "cloudpress"
|
8
|
+
spec.version = Cloudpress::VERSION
|
9
|
+
spec.authors = ["Adam Carlile"]
|
10
|
+
spec.email = ["adam@benchmedia.co.uk"]
|
11
|
+
|
12
|
+
spec.summary = "A blogging framework that uses dropbox as it's storage engine"
|
13
|
+
spec.homepage = "http://github.com/adamcarlile/cloudpress"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
17
|
+
spec.bindir = "exe"
|
18
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency "dropbox-sdk"
|
22
|
+
spec.add_dependency "metadown"
|
23
|
+
spec.add_dependency "pygments.rb"
|
24
|
+
spec.add_dependency "nokogiri"
|
25
|
+
spec.add_dependency "kaminari"
|
26
|
+
spec.add_dependency "builder"
|
27
|
+
spec.add_dependency "groupdate"
|
28
|
+
spec.add_dependency "slim"
|
29
|
+
spec.add_dependency "acts-as-taggable-on"
|
30
|
+
spec.add_dependency "friendly_id"
|
31
|
+
spec.add_dependency "rails", "~> 4.2.0"
|
32
|
+
|
33
|
+
spec.add_development_dependency "bundler", "~> 1.8"
|
34
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
35
|
+
end
|
data/config/routes.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
class CreateCloudpressPosts < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :cloudpress_posts do |t|
|
4
|
+
t.string :title
|
5
|
+
t.string :slug
|
6
|
+
t.string :file_path
|
7
|
+
t.string :revision
|
8
|
+
t.string :state
|
9
|
+
t.text :body
|
10
|
+
t.json :metadata
|
11
|
+
t.datetime :publish_date
|
12
|
+
t.timestamps null: false
|
13
|
+
end
|
14
|
+
|
15
|
+
add_index :cloudpress_posts, :state
|
16
|
+
add_index :cloudpress_posts, :slug
|
17
|
+
add_index :cloudpress_posts, :file_path
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
class CreateTagsTable < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :tags do |t|
|
4
|
+
t.string :name
|
5
|
+
end
|
6
|
+
|
7
|
+
create_table :taggings do |t|
|
8
|
+
t.references :tag
|
9
|
+
|
10
|
+
# You should make sure that the column created is
|
11
|
+
# long enough to store the required class names.
|
12
|
+
t.references :taggable, :polymorphic => true
|
13
|
+
t.references :tagger, :polymorphic => true
|
14
|
+
|
15
|
+
# Limit is created to prevent MySQL error on index
|
16
|
+
# length for MyISAM table type: http://bit.ly/vgW2Ql
|
17
|
+
t.string :context, :limit => 128
|
18
|
+
|
19
|
+
t.datetime :created_at
|
20
|
+
end
|
21
|
+
|
22
|
+
add_index :taggings, :tag_id
|
23
|
+
add_index :taggings, [:taggable_id, :taggable_type, :context]
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.down
|
27
|
+
drop_table :taggings
|
28
|
+
drop_table :tags
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class CreateFriendlyIdSlugs < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :friendly_id_slugs do |t|
|
4
|
+
t.string :slug, :null => false
|
5
|
+
t.integer :sluggable_id, :null => false
|
6
|
+
t.string :sluggable_type, :limit => 50
|
7
|
+
t.string :scope
|
8
|
+
t.datetime :created_at
|
9
|
+
end
|
10
|
+
add_index :friendly_id_slugs, :sluggable_id
|
11
|
+
add_index :friendly_id_slugs, [:slug, :sluggable_type]
|
12
|
+
add_index :friendly_id_slugs, [:slug, :sluggable_type, :scope], :unique => true
|
13
|
+
add_index :friendly_id_slugs, :sluggable_type
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class AddTaggingsCounterCache < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
add_column :tags, :taggings_count, :integer, default: 0
|
4
|
+
|
5
|
+
ActsAsTaggableOn::Tag.reset_column_information
|
6
|
+
ActsAsTaggableOn::Tag.find_each do |tag|
|
7
|
+
ActsAsTaggableOn::Tag.reset_counters(tag.id, :taggings)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.down
|
12
|
+
remove_column :tags, :taggings_count
|
13
|
+
end
|
14
|
+
end
|
data/lib/cloudpress.rb
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
require "dropbox_sdk"
|
2
|
+
require "metadown"
|
3
|
+
require "redcarpet"
|
4
|
+
require "pygments"
|
5
|
+
require "kaminari"
|
6
|
+
require "groupdate"
|
7
|
+
require "slim"
|
8
|
+
require "friendly_id"
|
9
|
+
require "acts-as-taggable-on"
|
10
|
+
require "cloudpress/version"
|
11
|
+
require "cloudpress/engine"
|
12
|
+
|
13
|
+
require "cloudpress/formatters/html_with_pygments"
|
14
|
+
require "cloudpress/dropbox/client"
|
15
|
+
require "cloudpress/dropbox/connector"
|
16
|
+
require "cloudpress/dropbox/directory"
|
17
|
+
require "cloudpress/dropbox/file"
|
18
|
+
require "cloudpress/dropbox/cleaner"
|
19
|
+
|
20
|
+
require "cloudpress/renderers/archive"
|
21
|
+
require "cloudpress/renderers/archives"
|
22
|
+
require "cloudpress/renderers/post"
|
23
|
+
require "cloudpress/renderers/posts"
|
24
|
+
require "cloudpress/renderers/tag"
|
25
|
+
require "cloudpress/renderers/tags"
|
26
|
+
|
27
|
+
module Cloudpress
|
28
|
+
|
29
|
+
module_function
|
30
|
+
|
31
|
+
def config
|
32
|
+
@config ? @config : configure
|
33
|
+
end
|
34
|
+
|
35
|
+
def configure &block
|
36
|
+
@config = ActiveSupport::OrderedOptions.new
|
37
|
+
@config.app_key = nil
|
38
|
+
@config.app_secret = nil
|
39
|
+
@config.app_token = nil
|
40
|
+
@config.base_path = 'cloudpress'
|
41
|
+
@config.live_path = 'live'
|
42
|
+
@config.draft_path = 'draft'
|
43
|
+
@config.markdown_renderer = Redcarpet::Markdown.new(Formatters::HTMLWithPygments, fenced_code_blocks: true)
|
44
|
+
yield(@config) if block_given?
|
45
|
+
@config
|
46
|
+
end
|
47
|
+
|
48
|
+
def base_path
|
49
|
+
"/#{config.base_path}"
|
50
|
+
end
|
51
|
+
|
52
|
+
def reload!
|
53
|
+
@file_index = nil
|
54
|
+
end
|
55
|
+
|
56
|
+
def live_path
|
57
|
+
[base_path, config.live_path].join('/')
|
58
|
+
end
|
59
|
+
|
60
|
+
def draft_path
|
61
|
+
[base_path, config.draft_path].join('/')
|
62
|
+
end
|
63
|
+
|
64
|
+
def update!
|
65
|
+
reload!
|
66
|
+
import!
|
67
|
+
purge!
|
68
|
+
end
|
69
|
+
|
70
|
+
def import!
|
71
|
+
file_index.values.each {|x| x.import!}
|
72
|
+
end
|
73
|
+
|
74
|
+
def purge!
|
75
|
+
Cloudpress::Dropbox::Cleaner.new(remote_paths, local_paths).clean!
|
76
|
+
end
|
77
|
+
|
78
|
+
def file_index
|
79
|
+
@file_index ||= {
|
80
|
+
live: Cloudpress::Dropbox::Directory.new(client, live_path, :live),
|
81
|
+
draft: Cloudpress::Dropbox::Directory.new(client, draft_path, :draft)
|
82
|
+
}
|
83
|
+
end
|
84
|
+
|
85
|
+
def client
|
86
|
+
@client ||= Cloudpress::Dropbox::Client.new(config.app_token)
|
87
|
+
end
|
88
|
+
|
89
|
+
def unconfigured?
|
90
|
+
config.app_key.blank? || config.app_secret.blank?
|
91
|
+
end
|
92
|
+
|
93
|
+
def unauthorized?
|
94
|
+
config.app_token.blank?
|
95
|
+
end
|
96
|
+
|
97
|
+
def remote_paths
|
98
|
+
file_index.values.map {|x| x.paths }.flatten
|
99
|
+
end
|
100
|
+
|
101
|
+
def local_paths
|
102
|
+
Cloudpress::Post.pluck(:file_path)
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Cloudpress
|
2
|
+
module Dropbox
|
3
|
+
class Cleaner
|
4
|
+
|
5
|
+
def initialize(remote_paths, local_paths)
|
6
|
+
@local_paths = local_paths
|
7
|
+
@remote_paths = remote_paths
|
8
|
+
end
|
9
|
+
|
10
|
+
def orphaned_paths
|
11
|
+
@orphaned_paths ||= @local_paths - @remote_paths
|
12
|
+
end
|
13
|
+
|
14
|
+
def clean!
|
15
|
+
Post.where(file_path: orphaned_paths).destroy_all if orphaned_paths.any?
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Cloudpress
|
2
|
+
module Dropbox
|
3
|
+
class Connector
|
4
|
+
|
5
|
+
def initialize(key, secret)
|
6
|
+
@key = key
|
7
|
+
@secret = secret
|
8
|
+
end
|
9
|
+
|
10
|
+
def flow
|
11
|
+
@flow ||= DropboxOAuth2FlowNoRedirect.new(@key, @secret)
|
12
|
+
end
|
13
|
+
|
14
|
+
def authorize_url
|
15
|
+
@authorize_url ||= flow.start
|
16
|
+
end
|
17
|
+
|
18
|
+
def authorize!(code)
|
19
|
+
flow.finish(code)
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Cloudpress
|
2
|
+
module Dropbox
|
3
|
+
class Directory
|
4
|
+
|
5
|
+
attr_reader :path, :client, :state
|
6
|
+
|
7
|
+
def initialize(client, path, state)
|
8
|
+
@client = client
|
9
|
+
@path = path
|
10
|
+
@state = state
|
11
|
+
end
|
12
|
+
|
13
|
+
def import!
|
14
|
+
files.each { |x| x.import! }
|
15
|
+
subdirectories.each {|x| x.import! }
|
16
|
+
end
|
17
|
+
|
18
|
+
def paths
|
19
|
+
@paths ||= begin
|
20
|
+
files.map {|x| x.path } + subdirectories.map { |x| x.paths }
|
21
|
+
end.flatten.compact.uniq
|
22
|
+
end
|
23
|
+
|
24
|
+
def directory_contents
|
25
|
+
remote_path_metadata.with_indifferent_access[:contents]
|
26
|
+
end
|
27
|
+
|
28
|
+
def files
|
29
|
+
@files ||= directory_contents.select { |x| x[:is_dir] == false }.map do |x|
|
30
|
+
Cloudpress::Dropbox::File.new(x[:path], x[:rev], state)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def subdirectories
|
35
|
+
@subdirectories ||= directory_contents.select { |x| x[:is_dir] == true }.map do |x|
|
36
|
+
Cloudpress::Dropbox::Directory.new(client, x[:path], state)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def create_path!
|
43
|
+
client.connection.file_create_folder path
|
44
|
+
end
|
45
|
+
|
46
|
+
def remote_path_metadata
|
47
|
+
@remote_path_metadata ||= begin
|
48
|
+
client.connection.metadata(path)
|
49
|
+
rescue DropboxError
|
50
|
+
create_path!
|
51
|
+
client.connection.metadata(path)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|