bread-basket 0.0.0 → 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 +4 -4
- data/.rspec +4 -0
- data/.rubocop.yml +18 -0
- data/.travis.yml +4 -1
- data/Gemfile +1 -1
- data/Guardfile +7 -2
- data/README.md +28 -17
- data/Rakefile +13 -6
- data/bin/bread-basket +14 -0
- data/bread-basket.gemspec +29 -24
- data/lib/bread/basket.rb +12 -6
- data/lib/bread/basket/cli.rb +10 -0
- data/lib/bread/basket/poster.rb +38 -0
- data/lib/bread/basket/poster/block_code_handler.rb +50 -0
- data/lib/bread/basket/poster/block_renderer.rb +14 -0
- data/lib/bread/basket/poster/box.rb +119 -0
- data/lib/bread/basket/poster/box_checker.rb +60 -0
- data/lib/bread/basket/poster/columns.rb +90 -0
- data/lib/bread/basket/poster/css_reader.rb +130 -0
- data/lib/bread/basket/poster/dimensions_helper.rb +123 -0
- data/lib/bread/basket/poster/header_callback.rb +29 -0
- data/lib/bread/basket/poster/header_maker.rb +74 -0
- data/lib/bread/basket/poster/image_box.rb +93 -0
- data/lib/bread/basket/poster/layout.rb +108 -0
- data/lib/bread/basket/poster/pdf_builder.rb +113 -0
- data/lib/bread/basket/poster/poster_maker.rb +55 -0
- data/lib/bread/basket/poster/prawn_patches/column_box.rb +17 -0
- data/lib/bread/basket/poster/text_renderer.rb +89 -0
- data/lib/bread/basket/poster/units_helper.rb +39 -0
- data/lib/bread/basket/version.rb +1 -1
- data/samples/block_sample.css +86 -0
- data/samples/flow_sample.css +68 -0
- data/samples/ipsum.jpg +0 -0
- data/samples/lorem.jpg +0 -0
- data/samples/lorem_block.md +86 -0
- data/samples/lorem_flow.md +58 -0
- data/samples/lorem_flow.pdf +3834 -6
- data/samples/sample.md +59 -0
- data/samples/simple.css +19 -0
- data/samples/simple.md +3 -0
- data/samples/ucair_logo.png +0 -0
- data/spec/cli_spec.rb +13 -0
- data/spec/poster/block_code_handler_spec.rb +47 -0
- data/spec/poster/box_spec.rb +114 -0
- data/spec/poster/columns_spec.rb +64 -0
- data/spec/poster/css_reader_spec.rb +115 -0
- data/spec/poster/header_maker_spec.rb +49 -0
- data/spec/poster/image_box_spec.rb +69 -0
- data/spec/poster/layout_spec.rb +75 -0
- data/spec/poster/pdf_builder_spec.rb +60 -0
- data/spec/poster/poster_maker_spec.rb +15 -0
- data/spec/poster/test_files/bad_file.md +1 -0
- data/spec/poster/test_files/basic_block.css +14 -0
- data/spec/poster/test_files/basic_flow.css +31 -0
- data/spec/poster/test_files/block_code_test.css +13 -0
- data/spec/poster/test_files/builder.css +39 -0
- data/spec/poster/test_files/circular.css +39 -0
- data/spec/poster/test_files/dragon.png +0 -0
- data/spec/poster/test_files/fitted_image.css +39 -0
- data/spec/poster/test_files/good_file.md +5 -0
- data/spec/poster/test_files/good_file.pdf +0 -0
- data/spec/poster/test_files/header_test.css +22 -0
- data/spec/poster/test_files/nearly_empty.css +10 -0
- data/spec/poster/test_files/self_referential.css +108 -0
- data/spec/poster/test_files/ucair_logo.png +0 -0
- data/spec/poster/text_renderer_spec.rb +54 -0
- data/spec/poster/units_helper_spec.rb +36 -0
- data/spec/spec_helper.rb +6 -0
- metadata +212 -34
- data/bread-basket-0.0.1.gem +0 -0
- data/spec/basket_spec.rb +0 -7
@@ -0,0 +1,69 @@
|
|
1
|
+
describe Bread::Basket::Poster::ImageBox do
|
2
|
+
# explanation of before all in css_reader_spec
|
3
|
+
# this is identical to the one used in Box since ImageBox
|
4
|
+
# is a subclass of Box
|
5
|
+
context 'with basic stylesheet' do
|
6
|
+
before(:all) do
|
7
|
+
metadata = { 'stylesheet' => 'self_referential' }
|
8
|
+
Bread::Basket::Poster.dir_path = './spec/poster/test_files'
|
9
|
+
@name = '.simple-selector'
|
10
|
+
@layout = Bread::Basket::Poster::Layout.new(metadata)
|
11
|
+
end
|
12
|
+
|
13
|
+
describe 'image has dimensions' do
|
14
|
+
subject { @layout.drgn_image }
|
15
|
+
its(:top) { should eq(720) }
|
16
|
+
its(:right) { should eq(1080) }
|
17
|
+
its(:height) { should eq(412) }
|
18
|
+
its(:width) { should eq(504) }
|
19
|
+
end
|
20
|
+
|
21
|
+
it "fails when the image can't be found" do
|
22
|
+
expect do
|
23
|
+
@specs = { 'src' => 'drgn.png', 'top' => 33, 'left' => 43 }
|
24
|
+
Bread::Basket::Poster::ImageBox.new('.bread-box', @layout, @specs)
|
25
|
+
end.to raise_error SystemExit
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'with fitted-image' do
|
30
|
+
before(:all) do
|
31
|
+
metadata = { 'stylesheet' => 'fitted_image' }
|
32
|
+
Bread::Basket::Poster.dir_path = './spec/poster/test_files'
|
33
|
+
@name = '.simple-selector'
|
34
|
+
@layout = Bread::Basket::Poster::Layout.new(metadata)
|
35
|
+
end
|
36
|
+
|
37
|
+
describe 'fixed width matches width, fits height' do
|
38
|
+
subject { @layout.drgn_image1 }
|
39
|
+
its(:width) { should eq(400) }
|
40
|
+
its(:height) { should be_within(0.02).of(327) }
|
41
|
+
end
|
42
|
+
|
43
|
+
describe 'fixed height matches height, fits width' do
|
44
|
+
subject { @layout.drgn_image2 }
|
45
|
+
its(:height) { should eq(400) }
|
46
|
+
its(:width) { should be_within(0.025).of(489.3) }
|
47
|
+
end
|
48
|
+
|
49
|
+
describe 'fixed width and height where height < width, matches height and fits width' do
|
50
|
+
subject { @layout.drgn_image3 }
|
51
|
+
its(:width) { should eq(300) }
|
52
|
+
its(:height) { should be_within(0.01).of(245.23) }
|
53
|
+
end
|
54
|
+
|
55
|
+
describe 'fixed width and height where width < height, matches height and fits width' do
|
56
|
+
subject { @layout.drgn_image4 }
|
57
|
+
its(:height) { should eq(300) }
|
58
|
+
its(:width) { should be_within(0.01).of(367) }
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'inspects itself' do
|
62
|
+
# I suspect this isn't ideal, I just copied and pasted the output to get this string
|
63
|
+
inspect_string = 'top: 1000.0; left: 600.0; width: 400.0; height: 326.984126984127;' \
|
64
|
+
' bottom: 673.015873015873; right: 1000.0; box_width: 400.0;' \
|
65
|
+
' box_height: 412; im_width: 400.0; im_height: 326.984126984127;'
|
66
|
+
expect(@layout.drgn_image1.inspect).to eq inspect_string
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
describe Bread::Basket::Poster::Layout do
|
2
|
+
def layout_obj(metadata)
|
3
|
+
Bread::Basket::Poster::Layout.new(metadata)
|
4
|
+
end
|
5
|
+
|
6
|
+
context 'when metadata is meaningless' do
|
7
|
+
let(:metadata) { { key: 'value' } }
|
8
|
+
let(:body) { 'Hello :bread:!' }
|
9
|
+
subject { Bread::Basket::Poster::Layout.new(metadata) }
|
10
|
+
|
11
|
+
it 'has metadata' do
|
12
|
+
expect(subject.metadata).to eq(metadata)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'creates a css-reader' do
|
16
|
+
expect(subject.css_reader).to be_a Bread::Basket::Poster::CSSReader
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'defaults to flow template' do
|
20
|
+
expect(subject.stylesheet).to include('samples/flow_sample.css')
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'creates attributes for itself and cleans up method name' do
|
24
|
+
subject.create_attribute('.jelly-beans', :magic)
|
25
|
+
expect(subject.jelly_beans).to eq :magic
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'for various values of metadata' do
|
30
|
+
it 'uses the given stylesheet' do
|
31
|
+
metadata = { 'stylesheet' => 'flow_sample' }
|
32
|
+
Bread::Basket::Poster.dir_path = './samples'
|
33
|
+
subject = layout_obj(metadata)
|
34
|
+
expect(subject.stylesheet).to include('flow_sample.css')
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'lays out a flow when layout is unrecognized' do
|
38
|
+
metadata = { 'layout' => 'jellybean' }
|
39
|
+
subject = layout_obj(metadata)
|
40
|
+
expect(subject.type).to eq(:flow)
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'lays out a flow when layout is nil' do
|
44
|
+
metadata = {}
|
45
|
+
subject = layout_obj(metadata)
|
46
|
+
expect(subject.type).to eq(:flow)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context 'when layout is flow' do
|
51
|
+
let(:metadata) { { 'layout' => 'flow' } }
|
52
|
+
subject { layout_obj(metadata) }
|
53
|
+
|
54
|
+
it 'lays out a flow' do
|
55
|
+
expect(subject.type).to eq(:flow)
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'knows that flows flow' do
|
59
|
+
expect(subject.flow?).to eql(true)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context 'when layout is block' do
|
64
|
+
let(:metadata) { { 'layout' => 'block' } }
|
65
|
+
subject { layout_obj(metadata) }
|
66
|
+
|
67
|
+
it 'lays out a block' do
|
68
|
+
expect(subject.type).to eq(:block)
|
69
|
+
end
|
70
|
+
|
71
|
+
it "knows that blocks don't flow" do
|
72
|
+
expect(subject.flow?).to eq(false)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
describe Bread::Basket::Poster::PDFBuilder do
|
2
|
+
context 'when metadata contains boxes' do
|
3
|
+
# explanation of before(:each) in css_reader_spec
|
4
|
+
before(:each) do
|
5
|
+
metadata = { 'stylesheet' => 'builder',
|
6
|
+
'A' => 'Box content!',
|
7
|
+
'S1' => 'Stretchy content!',
|
8
|
+
'B' => 'Box content!',
|
9
|
+
'S2' => 'Stretchy content!'
|
10
|
+
}
|
11
|
+
Bread::Basket::Poster.dir_path = './spec/poster/test_files'
|
12
|
+
Bread::Basket::Poster.layout = Bread::Basket::Poster::Layout.new(metadata)
|
13
|
+
end
|
14
|
+
|
15
|
+
subject { Bread::Basket::Poster::PDFBuilder.new }
|
16
|
+
|
17
|
+
it 'creates a PDF' do
|
18
|
+
expect(subject.pdf).to be_a Prawn::Document
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'creates a text_renderer' do
|
22
|
+
expect(subject.text_renderer).to be_a Redcarpet::Markdown
|
23
|
+
end
|
24
|
+
|
25
|
+
# this stylesheet has lots of dependence on stretchy boxes to check for builder's
|
26
|
+
# ability to resolve them *after* stretchy size has been determined
|
27
|
+
# BEFORE
|
28
|
+
it 'starts out with most boxes pending' do
|
29
|
+
expect(subject.layout.pending).to eq %w(columns[0] .A .S2 .B)
|
30
|
+
end
|
31
|
+
|
32
|
+
# AFTER
|
33
|
+
it 'builds the boxes and leaves none pending' do
|
34
|
+
subject.boxes_from_metadata
|
35
|
+
expect(subject.layout.pending).to eq []
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context 'when given a circular stylesheet' do
|
40
|
+
before(:all) do
|
41
|
+
metadata = { 'stylesheet' => 'circular',
|
42
|
+
'A' => 'Box content!',
|
43
|
+
'S1' => 'Stretchy content!',
|
44
|
+
'B' => 'Box content!',
|
45
|
+
'S2' => 'Stretchy content!'
|
46
|
+
}
|
47
|
+
Bread::Basket::Poster.dir_path = './spec/poster/test_files'
|
48
|
+
Bread::Basket::Poster.layout = Bread::Basket::Poster::Layout.new(metadata)
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'should fail to resolve any boxes' do
|
52
|
+
subject.boxes_from_metadata
|
53
|
+
expect(subject.layout.pending).to eq %w(columns[0] .S1 .A .S2 .B)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context 'when boxes are in body only' do
|
58
|
+
# BLOCKS
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
describe Bread::Basket::Poster::PosterMaker do
|
2
|
+
let(:file_path) { 'spec/poster/test_files/' }
|
3
|
+
let(:good_file) { File.expand_path file_path + 'good_file.md' }
|
4
|
+
let(:bad_file) { File.expand_path file_path + 'bad_file.md' }
|
5
|
+
subject { Bread::Basket::Poster::PosterMaker }
|
6
|
+
|
7
|
+
it 'succeeds if the file has front matter' do
|
8
|
+
expect { subject.new(good_file) }.not_to raise_error
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'fails if the file has no front matter' do
|
12
|
+
error = Bread::Basket::Poster::NoFrontMatterError
|
13
|
+
expect { subject.new(bad_file) }.to raise_error(error)
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
No front matter!
|
@@ -0,0 +1,31 @@
|
|
1
|
+
.layout {
|
2
|
+
width: 1080;
|
3
|
+
height: 720;
|
4
|
+
margin: 5;
|
5
|
+
|
6
|
+
font-size: 24;
|
7
|
+
font-family: times;
|
8
|
+
}
|
9
|
+
|
10
|
+
.columns {
|
11
|
+
count: 4;
|
12
|
+
top: 648, 576;
|
13
|
+
}
|
14
|
+
|
15
|
+
.stretchy-box {
|
16
|
+
top: 100;
|
17
|
+
left: 200;
|
18
|
+
width: 500;
|
19
|
+
|
20
|
+
font-size: 22;
|
21
|
+
}
|
22
|
+
|
23
|
+
.image {
|
24
|
+
top: 720;
|
25
|
+
right: 1080;
|
26
|
+
src: dragon.png
|
27
|
+
}
|
28
|
+
|
29
|
+
#header {
|
30
|
+
background-color: #ffffff;
|
31
|
+
}
|
@@ -0,0 +1,39 @@
|
|
1
|
+
.layout {
|
2
|
+
width: 100;
|
3
|
+
height: 100;
|
4
|
+
margin: 5;
|
5
|
+
|
6
|
+
font-size: 24;
|
7
|
+
font-family: times;
|
8
|
+
}
|
9
|
+
|
10
|
+
.columns {
|
11
|
+
count: 1;
|
12
|
+
top: B.bottom;
|
13
|
+
}
|
14
|
+
|
15
|
+
.S1 {
|
16
|
+
top: top - margin;
|
17
|
+
left: left + margin;
|
18
|
+
width: width - 2 * margin;
|
19
|
+
}
|
20
|
+
|
21
|
+
.A {
|
22
|
+
left: left + margin;
|
23
|
+
top: S1.bottom - margin;
|
24
|
+
width: S1.width;
|
25
|
+
height: 10;
|
26
|
+
}
|
27
|
+
|
28
|
+
.S2 {
|
29
|
+
top: A.bottom - margin;
|
30
|
+
left: left + margin;
|
31
|
+
width: S1.width;
|
32
|
+
}
|
33
|
+
|
34
|
+
.B {
|
35
|
+
left: left + margin;
|
36
|
+
top: S2.bottom - margin;
|
37
|
+
width: S1.width;
|
38
|
+
height: 10;
|
39
|
+
}
|
@@ -0,0 +1,39 @@
|
|
1
|
+
.layout {
|
2
|
+
width: 100;
|
3
|
+
height: 100;
|
4
|
+
margin: 5;
|
5
|
+
|
6
|
+
font-size: 24;
|
7
|
+
font-family: times;
|
8
|
+
}
|
9
|
+
|
10
|
+
.columns {
|
11
|
+
count: 1;
|
12
|
+
top: B.bottom;
|
13
|
+
}
|
14
|
+
|
15
|
+
.S1 {
|
16
|
+
top: b.bottom - margin;
|
17
|
+
left: left + margin;
|
18
|
+
width: width - 2 * margin;
|
19
|
+
}
|
20
|
+
|
21
|
+
.A {
|
22
|
+
left: left + margin;
|
23
|
+
top: S1.bottom - margin;
|
24
|
+
width: S1.width;
|
25
|
+
height: 10;
|
26
|
+
}
|
27
|
+
|
28
|
+
.S2 {
|
29
|
+
top: A.bottom - margin;
|
30
|
+
left: left + margin;
|
31
|
+
width: S1.width;
|
32
|
+
}
|
33
|
+
|
34
|
+
.B {
|
35
|
+
left: left + margin;
|
36
|
+
top: S2.bottom - margin;
|
37
|
+
width: S1.width;
|
38
|
+
height: 10;
|
39
|
+
}
|
Binary file
|
@@ -0,0 +1,39 @@
|
|
1
|
+
.layout {
|
2
|
+
width: 1000;
|
3
|
+
height: 1000;
|
4
|
+
}
|
5
|
+
|
6
|
+
.columns {
|
7
|
+
top: 0;
|
8
|
+
count: 1;
|
9
|
+
}
|
10
|
+
|
11
|
+
.drgn-image1 {
|
12
|
+
top: 1000;
|
13
|
+
right: 1000;
|
14
|
+
width: 400;
|
15
|
+
src: dragon.png
|
16
|
+
}
|
17
|
+
|
18
|
+
.drgn-image2 {
|
19
|
+
top: 1000;
|
20
|
+
right: 1000;
|
21
|
+
height: 400;
|
22
|
+
src: dragon.png
|
23
|
+
}
|
24
|
+
|
25
|
+
.drgn-image3 {
|
26
|
+
top: 1000;
|
27
|
+
right: 1000;
|
28
|
+
height: 400;
|
29
|
+
width: 300;
|
30
|
+
src: dragon.png
|
31
|
+
}
|
32
|
+
|
33
|
+
.drgn-image4 {
|
34
|
+
top: 1000;
|
35
|
+
right: 1000;
|
36
|
+
height: 300;
|
37
|
+
width: 400;
|
38
|
+
src: dragon.png
|
39
|
+
}
|
Binary file
|
@@ -0,0 +1,22 @@
|
|
1
|
+
.layout {
|
2
|
+
width: 1000;
|
3
|
+
height: 1000;
|
4
|
+
}
|
5
|
+
|
6
|
+
.columns {
|
7
|
+
top: 0;
|
8
|
+
count: 1;
|
9
|
+
}
|
10
|
+
|
11
|
+
#header {
|
12
|
+
width: 300;
|
13
|
+
height: 55;
|
14
|
+
|
15
|
+
font-size: 73;
|
16
|
+
color: #cc00FF;
|
17
|
+
margin-top: 13;
|
18
|
+
margin-bottom: 17;
|
19
|
+
radius: 11;
|
20
|
+
background-color: #000000;
|
21
|
+
font-family: Courier;
|
22
|
+
}
|