cloudpress 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/.travis.yml +3 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +21 -0
  6. data/README.md +39 -0
  7. data/Rakefile +30 -0
  8. data/app/assets/cloudpress/cloudpress.css.sass +1 -0
  9. data/app/assets/cloudpress/code/railscasts.css +70 -0
  10. data/app/controllers/cloudpress/application_controller.rb +12 -0
  11. data/app/controllers/cloudpress/archives_controller.rb +34 -0
  12. data/app/controllers/cloudpress/posts_controller.rb +23 -0
  13. data/app/controllers/cloudpress/tags_controller.rb +20 -0
  14. data/app/helpers/cloudpress/renderer_helper.rb +23 -0
  15. data/app/jobs/cloudpress/update_posts_job.rb +9 -0
  16. data/app/models/cloudpress/archive.rb +50 -0
  17. data/app/models/cloudpress/post.rb +65 -0
  18. data/app/views/cloudpress/archives/_archive.html.slim +3 -0
  19. data/app/views/cloudpress/archives/_archives.html.slim +2 -0
  20. data/app/views/cloudpress/archives/_month.html.slim +2 -0
  21. data/app/views/cloudpress/archives/show.html.slim +1 -0
  22. data/app/views/cloudpress/posts/_intro.html.slim +9 -0
  23. data/app/views/cloudpress/posts/_post.html.slim +8 -0
  24. data/app/views/cloudpress/posts/index.html.slim +1 -0
  25. data/app/views/cloudpress/posts/show.html.slim +1 -0
  26. data/app/views/cloudpress/tags/_tag.html.slim +2 -0
  27. data/app/views/cloudpress/tags/_tags.html.slim +2 -0
  28. data/app/views/cloudpress/tags/show.html.slim +1 -0
  29. data/bin/console +14 -0
  30. data/bin/rails +12 -0
  31. data/bin/setup +7 -0
  32. data/cloudpress.gemspec +35 -0
  33. data/config/initializers/tag_extensions.rb +4 -0
  34. data/config/routes.rb +9 -0
  35. data/db/migrate/20150309115639_create_cloudpress_posts.rb +19 -0
  36. data/db/migrate/20150315192521_create_tags_table.rb +30 -0
  37. data/db/migrate/20150315193206_create_friendly_id_slugs.rb +15 -0
  38. data/db/migrate/20150317121651_add_slug_to_tags.rb +6 -0
  39. data/db/migrate/20150317122608_add_taggings_counter_cache.rb +14 -0
  40. data/lib/cloudpress.rb +105 -0
  41. data/lib/cloudpress/dropbox/cleaner.rb +20 -0
  42. data/lib/cloudpress/dropbox/client.rb +15 -0
  43. data/lib/cloudpress/dropbox/connector.rb +24 -0
  44. data/lib/cloudpress/dropbox/directory.rb +57 -0
  45. data/lib/cloudpress/dropbox/file.rb +57 -0
  46. data/lib/cloudpress/engine.rb +10 -0
  47. data/lib/cloudpress/formatters/html_with_pygments.rb +7 -0
  48. data/lib/cloudpress/renderers/archive.rb +18 -0
  49. data/lib/cloudpress/renderers/archives.rb +24 -0
  50. data/lib/cloudpress/renderers/post.rb +39 -0
  51. data/lib/cloudpress/renderers/posts.rb +38 -0
  52. data/lib/cloudpress/renderers/tag.rb +18 -0
  53. data/lib/cloudpress/renderers/tags.rb +24 -0
  54. data/lib/cloudpress/version.rb +3 -0
  55. data/lib/generators/cloudpress/initializer/USAGE +8 -0
  56. data/lib/generators/cloudpress/initializer/initializer_generator.rb +32 -0
  57. metadata +283 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 66f77b04e4f9ef5b8f64d4f609cb602cbcb958c4
4
+ data.tar.gz: 85e140b6936fc6cb99e4afeab8568e189b53df31
5
+ SHA512:
6
+ metadata.gz: a0149d95e94409c77310870b75b825c17e58ec6d54c44b964df7a0095085ee96ce9a7c1ae172f4567c69c7b59dd3d14a079fde2c5c4930e8fbef85e350a062ce
7
+ data.tar.gz: 83f1f9d14cb774ad0c01b5666ab3643fdeb841d912e6a319478f138f91ae114b2a660b80fc1b4b700fe629691632d57923c705bd01f55b66e23bae54811ce594
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ .DS_Store
data/.travis.yml ADDED
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.0
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in cloudpress.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Adam Carlile
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,39 @@
1
+ # Cloudpress
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/cloudpress`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'cloudpress'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install cloudpress
22
+
23
+ ## Usage
24
+
25
+ TODO: Write usage instructions here
26
+
27
+ ## Development
28
+
29
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/console` for an interactive prompt that will allow you to experiment.
30
+
31
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release` to create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
+
33
+ ## Contributing
34
+
35
+ 1. Fork it ( https://github.com/[my-github-username]/cloudpress/fork )
36
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
37
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
38
+ 4. Push to the branch (`git push origin my-new-feature`)
39
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,30 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'Blorgh'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.rdoc')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+
18
+ Bundler::GemHelper.install_tasks
19
+
20
+ require 'rake/testtask'
21
+
22
+ Rake::TestTask.new(:test) do |t|
23
+ t.libs << 'lib'
24
+ t.libs << 'test'
25
+ t.pattern = 'test/**/*_test.rb'
26
+ t.verbose = false
27
+ end
28
+
29
+
30
+ task default: :test
@@ -0,0 +1 @@
1
+ @import "code/railscasts"
@@ -0,0 +1,70 @@
1
+ .highlight { background: #2B2B2B; color: #E6E1DC}
2
+ .highlight .hll { background-color: #ffffcc }
3
+ .highlight .c { color: #BC9458; font-style: italic} /* Comment */
4
+ .highlight .err { color: #E6E1DC} /* Error */
5
+ .highlight .g { color: #E6E1DC} /* Generic */
6
+ .highlight .k { color: #CC7833} /* Keyword */
7
+ .highlight .l { color: #E6E1DC} /* Literal */
8
+ .highlight .n { color: #E6E1DC} /* Name */
9
+ .highlight .o { color: #E6E1DC} /* Operator */
10
+ .highlight .x { color: #E6E1DC} /* Other */
11
+ .highlight .p { color: #E6E1DC} /* Punctuation */
12
+ .highlight .cm { color: #BC9458; font-style: italic} /* Comment.Multiline */
13
+ .highlight .cp { color: #CC7833} /* Comment.Preproc */
14
+ .highlight .c1 { color: #BC9458; font-style: italic} /* Comment.Single */
15
+ .highlight .cs { color: #BC9458; font-style: italic} /* Comment.Special */
16
+ .highlight .gd { color: #E6E1DC; background-color: #660000 } /* Generic.Deleted */
17
+ .highlight .ge { color: #E6E1DC} /* Generic.Emph */
18
+ .highlight .gr { color: #FFFFFF; background-color: #990000 } /* Generic.Error */
19
+ .highlight .gh { color: #FFFFFF} /* Generic.Heading */
20
+ .highlight .gi { color: #E6E1DC; background-color: #144212 } /* Generic.Inserted */
21
+ .highlight .go { color: #E6E1DC} /* Generic.Output */
22
+ .highlight .gp { color: #E6E1DC} /* Generic.Prompt */
23
+ .highlight .gs { color: #E6E1DC} /* Generic.Strong */
24
+ .highlight .gu { color: #FFFFFF} /* Generic.Subheading */
25
+ .highlight .gt { color: #E6E1DC} /* Generic.Traceback */
26
+ .highlight .kc { color: #CC7833} /* Keyword.Constant */
27
+ .highlight .kd { color: #CC7833} /* Keyword.Declaration */
28
+ .highlight .kn { color: #CC7833} /* Keyword.Namespace */
29
+ .highlight .kp { color: #CC7833} /* Keyword.Pseudo */
30
+ .highlight .kr { color: #CC7833} /* Keyword.Reserved */
31
+ .highlight .kt { color: #DA4939} /* Keyword.Type */
32
+ .highlight .ld { color: #E6E1DC} /* Literal.Date */
33
+ .highlight .m { color: #A5C261} /* Literal.Number */
34
+ .highlight .s { color: #A5C261} /* Literal.String */
35
+ .highlight .na { color: #FFC66D} /* Name.Attribute */
36
+ .highlight .nb { color: #E6E1DC} /* Name.Builtin */
37
+ .highlight .nc { color: #E6E1DC} /* Name.Class */
38
+ .highlight .no { color: #6D9CBE} /* Name.Constant */
39
+ .highlight .nd { color: #E6E1DC} /* Name.Decorator */
40
+ .highlight .ni { color: #E6E1DC} /* Name.Entity */
41
+ .highlight .ne { color: #E6E1DC} /* Name.Exception */
42
+ .highlight .nf { color: #FFC66D} /* Name.Function */
43
+ .highlight .nl { color: #E6E1DC} /* Name.Label */
44
+ .highlight .nn { color: #E6E1DC} /* Name.Namespace */
45
+ .highlight .nx { color: #E6E1DC} /* Name.Other */
46
+ .highlight .py { color: #E6E1DC} /* Name.Property */
47
+ .highlight .nt { color: #CC7833} /* Name.Tag */
48
+ .highlight .nv { color: #D0D0FF} /* Name.Variable */
49
+ .highlight .ow { color: #E6E1DC} /* Operator.Word */
50
+ .highlight .w { color: #E6E1DC} /* Text.Whitespace */
51
+ .highlight .mf { color: #A5C261} /* Literal.Number.Float */
52
+ .highlight .mh { color: #A5C261} /* Literal.Number.Hex */
53
+ .highlight .mi { color: #A5C261} /* Literal.Number.Integer */
54
+ .highlight .mo { color: #A5C261} /* Literal.Number.Oct */
55
+ .highlight .sb { color: #A5C261} /* Literal.String.Backtick */
56
+ .highlight .sc { color: #A5C261} /* Literal.String.Char */
57
+ .highlight .sd { color: #A5C261} /* Literal.String.Doc */
58
+ .highlight .s2 { color: #A5C261} /* Literal.String.Double */
59
+ .highlight .se { color: #A5C261} /* Literal.String.Escape */
60
+ .highlight .sh { color: #A5C261} /* Literal.String.Heredoc */
61
+ .highlight .si { color: #A5C261} /* Literal.String.Interpol */
62
+ .highlight .sx { color: #A5C261} /* Literal.String.Other */
63
+ .highlight .sr { color: #A5C261} /* Literal.String.Regex */
64
+ .highlight .s1 { color: #A5C261} /* Literal.String.Single */
65
+ .highlight .ss { color: #A5C261} /* Literal.String.Symbol */
66
+ .highlight .bp { color: #E6E1DC} /* Name.Builtin.Pseudo */
67
+ .highlight .vc { color: #D0D0FF} /* Name.Variable.Class */
68
+ .highlight .vg { color: #D0D0FF} /* Name.Variable.Global */
69
+ .highlight .vi { color: #D0D0FF} /* Name.Variable.Instance */
70
+ .highlight .il { color: #A5C261} /* Literal.Number.Integer.Long */
@@ -0,0 +1,12 @@
1
+ module Cloudpress
2
+ class ApplicationController < ::ApplicationController
3
+
4
+ protected
5
+
6
+ def archives
7
+ @archives ||= Cloudpress::Archive.all
8
+ end
9
+ helper_method :archives
10
+
11
+ end
12
+ end
@@ -0,0 +1,34 @@
1
+ module Cloudpress
2
+ class ArchivesController < Cloudpress::ApplicationController
3
+
4
+ def show
5
+ end
6
+
7
+ private
8
+
9
+ def archive
10
+ @archive ||= begin
11
+ out = nil
12
+ date = Date.new *[params[:year], params[:month]].compact.map(&:to_i)
13
+ out = Cloudpress::Archive.year(date) if year?
14
+ out = Cloudpress::Archive.find(date) if year? && month?
15
+ out
16
+ end
17
+ end
18
+ helper_method :archive
19
+
20
+ def posts
21
+ @posts ||= archive.posts
22
+ end
23
+ helper_method :posts
24
+
25
+ def year?
26
+ params[:year].present?
27
+ end
28
+
29
+ def month?
30
+ params[:month].present?
31
+ end
32
+
33
+ end
34
+ end
@@ -0,0 +1,23 @@
1
+ module Cloudpress
2
+ class PostsController < Cloudpress::ApplicationController
3
+
4
+ def index
5
+ end
6
+
7
+ def show
8
+ end
9
+
10
+ protected
11
+
12
+ def posts
13
+ @posts ||= Cloudpress::Post.published.page(params[:page])
14
+ end
15
+ helper_method :posts
16
+
17
+ def post
18
+ @post ||= Cloudpress::Post.find_by(slug: params[:slug])
19
+ end
20
+ helper_method :post
21
+
22
+ end
23
+ end
@@ -0,0 +1,20 @@
1
+ module Cloudpress
2
+ class TagsController < Cloudpress::ApplicationController
3
+
4
+ def show
5
+ end
6
+
7
+ protected
8
+
9
+ def tagging
10
+ @tagging ||= ActsAsTaggableOn::Tag.find(params[:id])
11
+ end
12
+ helper_method :tagging
13
+
14
+ def posts
15
+ @posts ||= Cloudpress::Post.tagged_with(tagging.name)
16
+ end
17
+ helper_method :posts
18
+
19
+ end
20
+ end
@@ -0,0 +1,23 @@
1
+ module Cloudpress
2
+ module RendererHelper
3
+
4
+ def render_cloudpress_posts(posts, options={}, &block)
5
+ Cloudpress::Renderers::Posts.new(self, posts, options).render
6
+ end
7
+
8
+ def render_cloudpress_post(post, options={}, &block)
9
+ renderer = Cloudpress::Renderers::Post.new(self, post, options)
10
+ renderer.content = capture(&block) if block_given?
11
+ renderer.render
12
+ end
13
+
14
+ def render_cloudpress_tags(tags)
15
+ Cloudpress::Renderers::Tags.new(self, tags).render
16
+ end
17
+
18
+ def render_cloudpress_archives(archives)
19
+ Cloudpress::Renderers::Archives.new(self, archives).render
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,9 @@
1
+ module Cloudpress
2
+ class UpdatePostsJob < ActiveJob::Base
3
+ queue_as :default
4
+
5
+ def perform
6
+ Cloudpress.update!
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,50 @@
1
+ module Cloudpress
2
+ class Archive
3
+ class << self
4
+
5
+ def all
6
+ wrap(Cloudpress::Post.unscoped.published.group_by_month(:publish_date).count.keys.group_by {|x| x.year})
7
+ end
8
+
9
+ def year(date)
10
+ raise ArgumentError unless date.respond_to?(:year)
11
+ new(date_range(date.beginning_of_year..date.end_of_year))
12
+ end
13
+
14
+ def find(date)
15
+ raise ArgumentError unless date.respond_to?(:year)
16
+ new(date_range(date.beginning_of_month..date.end_of_month))
17
+ end
18
+
19
+ private
20
+
21
+ def wrap(hash)
22
+ hash.map { |k, v| new(date_range(v)) }
23
+ end
24
+
25
+ def date_range(range)
26
+ range.first.to_time.beginning_of_month.in_time_zone..range.last.to_time.end_of_month.in_time_zone
27
+ end
28
+
29
+ end
30
+
31
+ attr_reader :range
32
+
33
+ def initialize(range)
34
+ @range = range
35
+ end
36
+
37
+ def year
38
+ range.first.year
39
+ end
40
+
41
+ def months
42
+ @months ||= (range.first.to_date..range.last.to_date).map {|x| x.beginning_of_month}.uniq
43
+ end
44
+
45
+ def posts
46
+ @posts ||= Cloudpress::Post.published.between(@range)
47
+ end
48
+
49
+ end
50
+ end
@@ -0,0 +1,65 @@
1
+ module Cloudpress
2
+ class Post < ActiveRecord::Base
3
+ acts_as_taggable
4
+
5
+ default_scope -> { order(publish_date: :desc) }
6
+ scope :published, -> { where(state: 'live') }
7
+ scope :draft, -> { where(state: 'draft') }
8
+
9
+ scope :between, ->(date_range) { where(:publish_date => date_range) }
10
+
11
+ paginates_per 10
12
+
13
+ def update_from_dropbox(dropbox_file)
14
+ self.revision = dropbox_file.revision
15
+ self.body = dropbox_file.body
16
+ self.metadata = dropbox_file.metadata
17
+ self.title = metadata[:title] || titleized_file_name
18
+ self.publish_date = created_at || Time.now
19
+ self.publish_date = Time.parse(metadata[:publish_date]) if metadata[:publish_date]
20
+ self.slug = metadata[:slug] || generate_slug
21
+ self.tag_list = metadata_tags.map(&:downcase)
22
+ self.state = dropbox_file.state
23
+ save!
24
+ end
25
+
26
+ def to_param
27
+ slug
28
+ end
29
+
30
+ def layout
31
+ metadata[:layout]
32
+ end
33
+
34
+ def metadata
35
+ super.with_indifferent_access
36
+ end
37
+
38
+ def summary
39
+ @summary ||= Nokogiri::HTML(body).at_css('p').text
40
+ end
41
+
42
+ def wordcount
43
+ @wordcount ||= Nokogiri::HTML(body).inner_text.split(' ').size
44
+ end
45
+
46
+ def time_to_read
47
+ @time_to_read ||= ((wordcount.to_f / 200.0) * 60).to_i
48
+ end
49
+
50
+ private
51
+
52
+ def generate_slug
53
+ slug_parts = []
54
+ slug_parts << publish_date.year
55
+ slug_parts << publish_date.month
56
+ slug_parts << title.parameterize
57
+ slug_parts.join('/')
58
+ end
59
+
60
+ def metadata_tags
61
+ [metadata[:tags]].flatten.compact
62
+ end
63
+
64
+ end
65
+ end