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.
Files changed (71) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +4 -0
  3. data/.rubocop.yml +18 -0
  4. data/.travis.yml +4 -1
  5. data/Gemfile +1 -1
  6. data/Guardfile +7 -2
  7. data/README.md +28 -17
  8. data/Rakefile +13 -6
  9. data/bin/bread-basket +14 -0
  10. data/bread-basket.gemspec +29 -24
  11. data/lib/bread/basket.rb +12 -6
  12. data/lib/bread/basket/cli.rb +10 -0
  13. data/lib/bread/basket/poster.rb +38 -0
  14. data/lib/bread/basket/poster/block_code_handler.rb +50 -0
  15. data/lib/bread/basket/poster/block_renderer.rb +14 -0
  16. data/lib/bread/basket/poster/box.rb +119 -0
  17. data/lib/bread/basket/poster/box_checker.rb +60 -0
  18. data/lib/bread/basket/poster/columns.rb +90 -0
  19. data/lib/bread/basket/poster/css_reader.rb +130 -0
  20. data/lib/bread/basket/poster/dimensions_helper.rb +123 -0
  21. data/lib/bread/basket/poster/header_callback.rb +29 -0
  22. data/lib/bread/basket/poster/header_maker.rb +74 -0
  23. data/lib/bread/basket/poster/image_box.rb +93 -0
  24. data/lib/bread/basket/poster/layout.rb +108 -0
  25. data/lib/bread/basket/poster/pdf_builder.rb +113 -0
  26. data/lib/bread/basket/poster/poster_maker.rb +55 -0
  27. data/lib/bread/basket/poster/prawn_patches/column_box.rb +17 -0
  28. data/lib/bread/basket/poster/text_renderer.rb +89 -0
  29. data/lib/bread/basket/poster/units_helper.rb +39 -0
  30. data/lib/bread/basket/version.rb +1 -1
  31. data/samples/block_sample.css +86 -0
  32. data/samples/flow_sample.css +68 -0
  33. data/samples/ipsum.jpg +0 -0
  34. data/samples/lorem.jpg +0 -0
  35. data/samples/lorem_block.md +86 -0
  36. data/samples/lorem_flow.md +58 -0
  37. data/samples/lorem_flow.pdf +3834 -6
  38. data/samples/sample.md +59 -0
  39. data/samples/simple.css +19 -0
  40. data/samples/simple.md +3 -0
  41. data/samples/ucair_logo.png +0 -0
  42. data/spec/cli_spec.rb +13 -0
  43. data/spec/poster/block_code_handler_spec.rb +47 -0
  44. data/spec/poster/box_spec.rb +114 -0
  45. data/spec/poster/columns_spec.rb +64 -0
  46. data/spec/poster/css_reader_spec.rb +115 -0
  47. data/spec/poster/header_maker_spec.rb +49 -0
  48. data/spec/poster/image_box_spec.rb +69 -0
  49. data/spec/poster/layout_spec.rb +75 -0
  50. data/spec/poster/pdf_builder_spec.rb +60 -0
  51. data/spec/poster/poster_maker_spec.rb +15 -0
  52. data/spec/poster/test_files/bad_file.md +1 -0
  53. data/spec/poster/test_files/basic_block.css +14 -0
  54. data/spec/poster/test_files/basic_flow.css +31 -0
  55. data/spec/poster/test_files/block_code_test.css +13 -0
  56. data/spec/poster/test_files/builder.css +39 -0
  57. data/spec/poster/test_files/circular.css +39 -0
  58. data/spec/poster/test_files/dragon.png +0 -0
  59. data/spec/poster/test_files/fitted_image.css +39 -0
  60. data/spec/poster/test_files/good_file.md +5 -0
  61. data/spec/poster/test_files/good_file.pdf +0 -0
  62. data/spec/poster/test_files/header_test.css +22 -0
  63. data/spec/poster/test_files/nearly_empty.css +10 -0
  64. data/spec/poster/test_files/self_referential.css +108 -0
  65. data/spec/poster/test_files/ucair_logo.png +0 -0
  66. data/spec/poster/text_renderer_spec.rb +54 -0
  67. data/spec/poster/units_helper_spec.rb +36 -0
  68. data/spec/spec_helper.rb +6 -0
  69. metadata +212 -34
  70. data/bread-basket-0.0.1.gem +0 -0
  71. 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,14 @@
1
+ .layout {
2
+ width: 4.ft;
3
+ height: 3.ft;
4
+ margin: 1.in;
5
+
6
+ font-size: 36;
7
+ font-family: helvetica;
8
+ }
9
+
10
+ .box {
11
+ left: 0;
12
+ top: 0;
13
+ width: 150;
14
+ }
@@ -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,13 @@
1
+ .layout {
2
+ width: 1000;
3
+ height: 1000;
4
+ }
5
+
6
+ .columns {
7
+ top: 0;
8
+ count: 1;
9
+ }
10
+
11
+ #caption {
12
+ font-size: 20;
13
+ }
@@ -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
+ }
@@ -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
+ }
@@ -0,0 +1,5 @@
1
+ ---
2
+ key: 'value'
3
+ ---
4
+
5
+ Hello :bread:
@@ -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
+ }
@@ -0,0 +1,10 @@
1
+ /*Nearly Empty*/
2
+ .layout {
3
+ width: 1000;
4
+ height: 1000;
5
+ }
6
+
7
+ .columns {
8
+ top: 0;
9
+ count: 1;
10
+ }