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