twirly 0.0.1
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 +4 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +122 -0
- data/LICENSE +20 -0
- data/README.md +56 -0
- data/bin/twirly +6 -0
- data/config/initializers/trello.rb +4 -0
- data/lib/twirly/cli.rb +22 -0
- data/lib/twirly/commands/base.rb +14 -0
- data/lib/twirly/commands/fetch_user.rb +9 -0
- data/lib/twirly/commands/pick.rb +9 -0
- data/lib/twirly/commands/pull.rb +9 -0
- data/lib/twirly/commands.rb +6 -0
- data/lib/twirly/compiler.rb +26 -0
- data/lib/twirly/helpers/youtube.rb +37 -0
- data/lib/twirly/helpers.rb +3 -0
- data/lib/twirly/post.rb +81 -0
- data/lib/twirly/serializers/post.rb +21 -0
- data/lib/twirly/serializers/user.rb +20 -0
- data/lib/twirly/serializers.rb +6 -0
- data/lib/twirly/user.rb +31 -0
- data/lib/twirly/version.rb +3 -0
- data/lib/twirly.rb +45 -0
- data/spec/cli_spec.rb +24 -0
- data/spec/commands/fetch_user_spec.rb +16 -0
- data/spec/commands/pick_spec.rb +16 -0
- data/spec/commands/pull_spec.rb +10 -0
- data/spec/dummy/.bowerrc +3 -0
- data/spec/dummy/.gitignore +1 -0
- data/spec/dummy/Gemfile +12 -0
- data/spec/dummy/Gemfile.lock +116 -0
- data/spec/dummy/Guardfile +10 -0
- data/spec/dummy/assets/javascripts/app.coffee +3 -0
- data/spec/dummy/assets/javascripts/router.coffee +27 -0
- data/spec/dummy/assets/stylesheets/index.css.scss +17 -0
- data/spec/dummy/assets/stylesheets/partials/_header.css.scss +20 -0
- data/spec/dummy/assets/stylesheets/partials/_post.css.scss +19 -0
- data/spec/dummy/assets/stylesheets/partials/_reset.css.scss +425 -0
- data/spec/dummy/source/.gitkeep +0 -0
- data/spec/dummy/vendor/assets/bower_components/backbone/backbone.js +1608 -0
- data/spec/dummy/vendor/assets/bower_components/backbone/bower.json +9 -0
- data/spec/dummy/vendor/assets/bower_components/backbone/index.js +1 -0
- data/spec/dummy/vendor/assets/bower_components/jquery/bower.json +27 -0
- data/spec/dummy/vendor/assets/bower_components/jquery/dist/jquery.min.js +5 -0
- data/spec/dummy/vendor/assets/bower_components/underscore/bower.json +8 -0
- data/spec/dummy/vendor/assets/bower_components/underscore/underscore.js +1343 -0
- data/spec/factories/post.rb +9 -0
- data/spec/factories/trello/attachment.rb +17 -0
- data/spec/factories/trello/board.rb +20 -0
- data/spec/factories/trello/card.rb +56 -0
- data/spec/factories/trello/label.rb +19 -0
- data/spec/factories/trello/member.rb +16 -0
- data/spec/factories/user.rb +9 -0
- data/spec/post_spec.rb +155 -0
- data/spec/serializers/post_spec.rb +41 -0
- data/spec/serializers/user_spec.rb +34 -0
- data/spec/spec_helper.rb +19 -0
- data/spec/user_spec.rb +43 -0
- data/twirly.gemspec +38 -0
- data/twirly.yml.sample +4 -0
- metadata +324 -0
@@ -0,0 +1,17 @@
|
|
1
|
+
FactoryGirl.define do
|
2
|
+
factory :trello_attachment, class: Trello::Attachment do
|
3
|
+
skip_create
|
4
|
+
|
5
|
+
name { Faker::Lorem.word << '.png' }
|
6
|
+
id { SecureRandom.hex }
|
7
|
+
url 'https://trello-attachments.s3.amazonws.com/koko.png'
|
8
|
+
bytes { Random.new.rand(100..100_100) }
|
9
|
+
date { Time.now.to_s }
|
10
|
+
is_upload true
|
11
|
+
|
12
|
+
initialize_with do
|
13
|
+
attachment = Trello::Attachment.new attributes.stringify_keys
|
14
|
+
attachment
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
FactoryGirl.define do
|
2
|
+
factory :trello_board, class: Trello::Board do
|
3
|
+
skip_create
|
4
|
+
|
5
|
+
id { SecureRandom.hex }
|
6
|
+
short_id
|
7
|
+
name { "some board - #{short_id}" }
|
8
|
+
description 'this board is so great'
|
9
|
+
closed false
|
10
|
+
url "https://trello.com/b/NrYMTajk/foo-bar"
|
11
|
+
short_url "https://trello.com/b/NrYMTajk"
|
12
|
+
organization_id "53779c553c97bc8a506f83df"
|
13
|
+
|
14
|
+
initialize_with do
|
15
|
+
board = Trello::Board.new
|
16
|
+
attributes.each_pair { |k, v| board.attributes[k] = v }
|
17
|
+
board
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
FactoryGirl.define do
|
2
|
+
sequence :short_id
|
3
|
+
end
|
4
|
+
|
5
|
+
FactoryGirl.define do
|
6
|
+
factory :trello_card, class: Trello::Card do
|
7
|
+
skip_create
|
8
|
+
|
9
|
+
id { SecureRandom.hex }
|
10
|
+
short_id
|
11
|
+
name { "some card - #{short_id}" }
|
12
|
+
desc "---\ntags: pathway to [_], wesser\n---\n\n{% youtube 6TncafSqfyo %}"
|
13
|
+
due { Time.now }
|
14
|
+
closed false
|
15
|
+
url "https://trello.com/c/NrYMTajk/6-the-mushrooms-yard-of-my-head"
|
16
|
+
short_url "https://trello.com/c/NrYMTajk"
|
17
|
+
board_id "53779c553c97bc8a506f83df"
|
18
|
+
member_ids ["51597b21213b313631005042"]
|
19
|
+
list_id "53779c553c97bc8a506f83e0"
|
20
|
+
pos nil
|
21
|
+
last_activity_date { Time.now }
|
22
|
+
card_labels []
|
23
|
+
labels []
|
24
|
+
cover_image_id nil
|
25
|
+
|
26
|
+
association :attachments, factory: :trello_attachment
|
27
|
+
|
28
|
+
trait :published do
|
29
|
+
due { (DateTime.now - 1).to_time }
|
30
|
+
|
31
|
+
card_labels do
|
32
|
+
[ { name: 'published' } ]
|
33
|
+
end
|
34
|
+
|
35
|
+
labels do
|
36
|
+
[ { name: 'published' } ]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
trait :unpublished do
|
41
|
+
due nil
|
42
|
+
end
|
43
|
+
|
44
|
+
trait :with_attachments do
|
45
|
+
after(:create) do |card|
|
46
|
+
card.stub(:attachments).and_return create_list(:trello_attachment, 5)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
initialize_with do
|
51
|
+
card = Trello::Card.new
|
52
|
+
attributes.each_pair { |k, v| card.attributes[k] = v }
|
53
|
+
card
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
FactoryGirl.define do
|
2
|
+
factory :trello_label, class: Trello::Label do
|
3
|
+
skip_create
|
4
|
+
|
5
|
+
name { "some label - #{short_id}" }
|
6
|
+
color { %w(red green purple).sample }
|
7
|
+
|
8
|
+
trait :published do
|
9
|
+
name 'published'
|
10
|
+
color 'green'
|
11
|
+
end
|
12
|
+
|
13
|
+
initialize_with do
|
14
|
+
label = Trello::Label.new
|
15
|
+
attributes.each_pair { |k, v| card.attributes[k] = v }
|
16
|
+
label
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
FactoryGirl.define do
|
2
|
+
factory :trello_member, class: Trello::Member do
|
3
|
+
skip_create
|
4
|
+
|
5
|
+
id { SecureRandom.hex }
|
6
|
+
username { Faker::Internet.user_name }
|
7
|
+
email { Faker::Internet.free_email }
|
8
|
+
bio { Faker::Lorem.sentence }
|
9
|
+
|
10
|
+
initialize_with do
|
11
|
+
member = Trello::Member.new
|
12
|
+
attributes.each_pair { |k, v| member.attributes[k] = v }
|
13
|
+
member
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/spec/post_spec.rb
ADDED
@@ -0,0 +1,155 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Twirly::Post do
|
4
|
+
let(:trello_board) { create(:trello_board) }
|
5
|
+
let(:trello_card) { create(:trello_card) }
|
6
|
+
let(:front_matter_content) do
|
7
|
+
<<-YAML.strip_heredoc.strip
|
8
|
+
---
|
9
|
+
important: true
|
10
|
+
tags: idm, punk, electro
|
11
|
+
---
|
12
|
+
YAML
|
13
|
+
end
|
14
|
+
|
15
|
+
let(:markdown_content) do
|
16
|
+
<<-MDN.strip_heredoc.strip
|
17
|
+
# A post about cats
|
18
|
+
> Everybody loves cats
|
19
|
+
{% youtube 320 280 4-IpnaqBhT4 %}
|
20
|
+
MDN
|
21
|
+
end
|
22
|
+
|
23
|
+
let(:post) { Twirly::Post.new(trello_card) }
|
24
|
+
subject { post }
|
25
|
+
|
26
|
+
describe '#card' do
|
27
|
+
it 'returns a Trello::Card' do
|
28
|
+
expect(subject.card.class).to eq(Trello::Card)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe '#title' do
|
33
|
+
it "is delegated to the card's name" do
|
34
|
+
expect(subject.title).to eq(subject.card.name)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe '#updated_at' do
|
39
|
+
it "is delegated to the card's last_activity_date" do
|
40
|
+
expect(subject.updated_at).to eq(subject.card.last_activity_date)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe '#created_at' do
|
45
|
+
it "is delegated to the card's due" do
|
46
|
+
expect(subject.created_at).to eq(subject.card.due)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe '#published_at' do
|
51
|
+
it "is delegated to the card's due" do
|
52
|
+
expect(subject.published_at).to eq(subject.card.due)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe '#card_id' do
|
57
|
+
it "is delegated to the card's id" do
|
58
|
+
expect(subject.card_id).to eq(subject.card.short_id)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe '#short_published_at' do
|
63
|
+
subject { post.short_published_at }
|
64
|
+
|
65
|
+
it { expect(subject).to eq(trello_card.due.strftime('%Y-%m-%d')) }
|
66
|
+
end
|
67
|
+
|
68
|
+
describe '#slug' do
|
69
|
+
subject { post.slug }
|
70
|
+
let(:slug) {"#{post.short_published_at}-#{post.title.parameterize}-#{post.card_id}" }
|
71
|
+
|
72
|
+
it { expect(subject).to eq(slug) }
|
73
|
+
end
|
74
|
+
|
75
|
+
describe '#authors' do
|
76
|
+
before do
|
77
|
+
subject.card.stub(:members).and_return(create_list(:trello_member, 3))
|
78
|
+
end
|
79
|
+
|
80
|
+
it "returns the decorated as Twirly::User(s) card members" do
|
81
|
+
expect(subject.authors.map(&:username))
|
82
|
+
.to match_array(subject.card.members.map(&:username))
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe '#tags' do
|
87
|
+
pending
|
88
|
+
end
|
89
|
+
|
90
|
+
describe '#body' do
|
91
|
+
pending
|
92
|
+
end
|
93
|
+
|
94
|
+
describe '#published?' do
|
95
|
+
context 'card is published (has published_at and the "published" label' do
|
96
|
+
let(:subject) do
|
97
|
+
post = Twirly::Post.new(create(:trello_card, :published))
|
98
|
+
post.card.stub(:labels).and_return([double(name: 'published')])
|
99
|
+
post
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'returns true' do
|
103
|
+
expect(subject).to be_published
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
context 'card is not published (has published_at and the "published" label' do
|
108
|
+
let(:subject) { Twirly::Post.new(create(:trello_card, :unpublished)) }
|
109
|
+
|
110
|
+
it 'returns false' do
|
111
|
+
expect(subject).to_not be_published
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
describe '.published' do
|
117
|
+
let(:unpublished_cards) do
|
118
|
+
create_list(:trello_card, 3, :unpublished).map do |card|
|
119
|
+
card.stub(:labels).and_return([])
|
120
|
+
card
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
let(:published_cards) do
|
125
|
+
create_list(:trello_card, 4, :published).map do |card|
|
126
|
+
card.stub(:labels).and_return([double(name: 'published')])
|
127
|
+
card
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
before do
|
132
|
+
Trello::Board.stub(:find).and_return(trello_board)
|
133
|
+
Twirly.board.stub(:cards).and_return(unpublished_cards + published_cards)
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'returns only posts decorating published cards' do
|
137
|
+
expect(Twirly::Post.published.map(&:card_id)).
|
138
|
+
to match_array(published_cards.map(&:short_id))
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
describe '.find' do
|
143
|
+
let(:matching_card) { create(:trello_card, short_id: 42) }
|
144
|
+
let(:non_matching_card) { create(:trello_card, short_id: 404) }
|
145
|
+
|
146
|
+
before do
|
147
|
+
Trello::Board.stub(:find).and_return(trello_board)
|
148
|
+
Twirly.board.stub(:cards).and_return([matching_card, non_matching_card])
|
149
|
+
end
|
150
|
+
|
151
|
+
it 'returns a card from the registered board with a matching trello short_id' do
|
152
|
+
expect(Twirly::Post.find(42).card_id).to eq(42)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Twirly::Serializers::Post do
|
4
|
+
let(:trello_board) { create(:trello_board) }
|
5
|
+
let(:trello_card) { create(:trello_card, :with_attachments) }
|
6
|
+
|
7
|
+
before do
|
8
|
+
trello_card.stub_chain(:list, :name).and_return 'music'
|
9
|
+
trello_card.stub(:labels).and_return([double(name: 'post-punk')])
|
10
|
+
end
|
11
|
+
|
12
|
+
let(:post) { Twirly::Post.new(trello_card) }
|
13
|
+
|
14
|
+
describe '#as_json' do
|
15
|
+
subject { post.as_json }
|
16
|
+
|
17
|
+
it 'is a Hash' do
|
18
|
+
expect(subject.as_json).to be_a(Hash)
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'has a root key' do
|
22
|
+
expect(subject[:post]).to be
|
23
|
+
end
|
24
|
+
|
25
|
+
describe 'representation attributes' do
|
26
|
+
subject { post.as_json[:post] }
|
27
|
+
|
28
|
+
its(:keys) { should match_array(%w[card_id title category tags
|
29
|
+
updated_at published_at].
|
30
|
+
map(&:to_sym)) }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe '#to_json' do
|
35
|
+
subject { post.to_json }
|
36
|
+
|
37
|
+
it 'is a String' do
|
38
|
+
expect(subject.to_json).to be_a(String)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Twirly::Serializers::User do
|
4
|
+
let(:trello_member) { create(:trello_member) }
|
5
|
+
|
6
|
+
let(:user) { Twirly::User.new(trello_member) }
|
7
|
+
|
8
|
+
describe '#as_json' do
|
9
|
+
subject { user.as_json }
|
10
|
+
|
11
|
+
it 'is a Hash' do
|
12
|
+
expect(subject.as_json).to be_a(Hash)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'has a root key' do
|
16
|
+
expect(subject[:user]).to be
|
17
|
+
end
|
18
|
+
|
19
|
+
describe 'representation attributes' do
|
20
|
+
subject { user.as_json[:user] }
|
21
|
+
|
22
|
+
its(:keys) { should match_array(%w[id username full_name bio avatar_url].
|
23
|
+
map(&:to_sym)) }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe '#to_json' do
|
28
|
+
subject { user.to_json }
|
29
|
+
|
30
|
+
it 'is a String' do
|
31
|
+
expect(subject.to_json).to be_a(String)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'twirly'
|
2
|
+
require 'factory_girl'
|
3
|
+
require 'faker'
|
4
|
+
|
5
|
+
RSpec.configure do |config|
|
6
|
+
# Formatting
|
7
|
+
config.formatter = :documentation
|
8
|
+
config.color_enabled = true
|
9
|
+
|
10
|
+
# Filtering
|
11
|
+
config.run_all_when_everything_filtered = true
|
12
|
+
config.filter_run focus: true
|
13
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
14
|
+
|
15
|
+
Dir['./spec/support/**/*.rb'].each(&method(:require))
|
16
|
+
Dir['./spec/factories/**/*.rb'].each(&method(:require))
|
17
|
+
|
18
|
+
config.include FactoryGirl::Syntax::Methods
|
19
|
+
end
|
data/spec/user_spec.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Twirly::User do
|
4
|
+
let(:trello_member) { create(:trello_member) }
|
5
|
+
|
6
|
+
subject { Twirly::User.new(trello_member) }
|
7
|
+
|
8
|
+
describe '#member' do
|
9
|
+
it 'returns a Trello::Member' do
|
10
|
+
expect(subject.member.class).to eq(Trello::Member)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe '.all' do
|
15
|
+
let(:board_members) { create_list(:trello_member, 3) }
|
16
|
+
let(:trello_board) { create(:trello_board) }
|
17
|
+
|
18
|
+
before do
|
19
|
+
Trello::Board.stub(:find).and_return(trello_board)
|
20
|
+
Twirly.board.stub(:members).and_return(board_members)
|
21
|
+
Twirly::User.any_instance.stub(:refresh!)
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'returns only users decorating board members' do
|
25
|
+
expect(Twirly::User.all.map(&:username)).
|
26
|
+
to match_array(board_members.map(&:username))
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe '.find_by_username' do
|
31
|
+
let(:matching_member) { create(:trello_member, username: 'zorbash') }
|
32
|
+
let(:non_matching_member) { create(:trello_member, username: 'zoidberg') }
|
33
|
+
|
34
|
+
before do
|
35
|
+
Twirly.board.stub(:members).and_return([matching_member, non_matching_member])
|
36
|
+
Twirly::User.any_instance.stub(:refresh!)
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'returns a user from the registered board with a matching trello username' do
|
40
|
+
expect(Twirly::User.find_by_username('zorbash').username).to eq('zorbash')
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/twirly.gemspec
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'twirly/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'twirly'
|
8
|
+
spec.version = Twirly::VERSION
|
9
|
+
spec.authors = ['Dimitris Zorbas']
|
10
|
+
spec.email = ['zorbash@skroutz.gr']
|
11
|
+
spec.description = <<-DESC
|
12
|
+
Publishing platform using trello
|
13
|
+
DESC
|
14
|
+
|
15
|
+
spec.summary = %q{Publishing platform using trello}
|
16
|
+
spec.homepage = 'https://github.com/Zorbash/twirly'
|
17
|
+
spec.license = 'MIT'
|
18
|
+
|
19
|
+
spec.files = `git ls-files`.split($/)
|
20
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
21
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
22
|
+
spec.require_paths = ['lib']
|
23
|
+
|
24
|
+
spec.add_development_dependency 'bundler', '~> 1.7'
|
25
|
+
spec.add_development_dependency 'rake'
|
26
|
+
spec.add_development_dependency 'pry'
|
27
|
+
spec.add_development_dependency 'pry-nav'
|
28
|
+
spec.add_development_dependency 'rspec', '~> 2.14.1'
|
29
|
+
spec.add_development_dependency 'guard-rspec'
|
30
|
+
spec.add_development_dependency 'rubocop'
|
31
|
+
spec.add_development_dependency 'faker'
|
32
|
+
spec.add_development_dependency 'factory_girl'
|
33
|
+
|
34
|
+
spec.add_dependency 'thor', '~> 1.19'
|
35
|
+
spec.add_dependency 'ruby-trello', '~> 1.1'
|
36
|
+
spec.add_dependency 'liquid', '~> 3.0'
|
37
|
+
spec.add_dependency 'json', '>= 1.8.1'
|
38
|
+
end
|
data/twirly.yml.sample
ADDED