squib 0.6.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (136) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +162 -133
  3. data/Gemfile +4 -4
  4. data/README.md +630 -550
  5. data/RELEASE TODO.md +18 -18
  6. data/Rakefile +99 -99
  7. data/lib/squib.rb +32 -32
  8. data/lib/squib/api/background.rb +20 -19
  9. data/lib/squib/api/data.rb +100 -99
  10. data/lib/squib/api/image.rb +90 -76
  11. data/lib/squib/api/save.rb +149 -103
  12. data/lib/squib/api/settings.rb +35 -37
  13. data/lib/squib/api/shapes.rb +230 -228
  14. data/lib/squib/api/text.rb +65 -66
  15. data/lib/squib/api/text_embed.rb +96 -66
  16. data/lib/squib/args/arg_loader.rb +138 -0
  17. data/lib/squib/args/box.rb +55 -0
  18. data/lib/squib/args/card_range.rb +32 -0
  19. data/lib/squib/args/color_validator.rb +12 -0
  20. data/lib/squib/args/coords.rb +33 -0
  21. data/lib/squib/args/dir_validator.rb +16 -0
  22. data/lib/squib/args/draw.rb +92 -0
  23. data/lib/squib/args/embed_adjust.rb +25 -0
  24. data/lib/squib/args/embed_key.rb +17 -0
  25. data/lib/squib/args/hand_special.rb +37 -0
  26. data/lib/squib/args/input_file.rb +37 -0
  27. data/lib/squib/args/paint.rb +44 -0
  28. data/lib/squib/args/paragraph.rb +115 -0
  29. data/lib/squib/args/save_batch.rb +60 -0
  30. data/lib/squib/args/scale_box.rb +53 -0
  31. data/lib/squib/args/sheet.rb +72 -0
  32. data/lib/squib/args/showcase_special.rb +38 -0
  33. data/lib/squib/args/svg_special.rb +37 -0
  34. data/lib/squib/args/transform.rb +25 -0
  35. data/lib/squib/args/typographer.rb +117 -117
  36. data/lib/squib/card.rb +67 -67
  37. data/lib/squib/conf.rb +117 -111
  38. data/lib/squib/constants.rb +178 -178
  39. data/lib/squib/deck.rb +113 -111
  40. data/lib/squib/graphics/cairo_context_wrapper.rb +99 -53
  41. data/lib/squib/graphics/gradient_regex.rb +46 -46
  42. data/lib/squib/graphics/hand.rb +42 -43
  43. data/lib/squib/graphics/image.rb +76 -73
  44. data/lib/squib/graphics/save_doc.rb +103 -137
  45. data/lib/squib/graphics/save_images.rb +33 -33
  46. data/lib/squib/graphics/shapes.rb +119 -152
  47. data/lib/squib/graphics/showcase.rb +85 -88
  48. data/lib/squib/graphics/text.rb +176 -216
  49. data/lib/squib/layout_parser.rb +91 -89
  50. data/lib/squib/layouts/economy.yml +85 -0
  51. data/lib/squib/layouts/fantasy.yml +101 -0
  52. data/lib/squib/layouts/hand.yml +62 -46
  53. data/lib/squib/layouts/playing-card.yml +35 -18
  54. data/lib/squib/project_template/config.yml +45 -40
  55. data/lib/squib/version.rb +10 -10
  56. data/samples/color_shortcuts.rb +6 -0
  57. data/samples/csv_import.rb +18 -18
  58. data/samples/custom-config.yml +5 -5
  59. data/samples/custom_config.rb +18 -18
  60. data/samples/draw_shapes.rb +45 -35
  61. data/samples/embed_text.rb +88 -90
  62. data/samples/hand.rb +24 -24
  63. data/samples/layouts.rb +62 -61
  64. data/samples/layouts_builtin.rb +51 -0
  65. data/samples/load_images.rb +78 -64
  66. data/samples/ranges.rb +64 -53
  67. data/samples/sample.csv +2 -2
  68. data/samples/text_options.rb +102 -94
  69. data/spec/api/api_data_spec.rb +57 -50
  70. data/spec/api/api_settings_spec.rb +37 -17
  71. data/spec/args/box_spec.rb +127 -0
  72. data/spec/args/draw_spec.rb +95 -0
  73. data/spec/args/embed_key_spec.rb +13 -0
  74. data/spec/args/input_file_spec.rb +21 -0
  75. data/spec/args/paint_spec.rb +22 -0
  76. data/spec/args/paragraph_spec.rb +153 -0
  77. data/spec/args/range_spec.rb +36 -0
  78. data/spec/args/save_batch_spec.rb +51 -0
  79. data/spec/args/scale_box_spec.rb +71 -0
  80. data/spec/args/sheet_spec.rb +58 -0
  81. data/spec/args/showcase_special_spec.rb +15 -0
  82. data/spec/data/samples/autoscale_font.rb.txt +84 -87
  83. data/spec/data/samples/basic.rb.txt +209 -203
  84. data/spec/data/samples/cairo_access.rb.txt +2 -2
  85. data/spec/data/samples/config_text_markup.rb.txt +72 -75
  86. data/spec/data/samples/csv_import.rb.txt +76 -80
  87. data/spec/data/samples/custom_config.rb.txt +48 -49
  88. data/spec/data/samples/draw_shapes.rb.txt +100 -42
  89. data/spec/data/samples/embed_text.rb.txt +283 -295
  90. data/spec/data/samples/excel.rb.txt +162 -171
  91. data/spec/data/samples/gradients.rb.txt +79 -67
  92. data/spec/data/samples/hand.rb.txt +538 -514
  93. data/spec/data/samples/hello_world.rb.txt +36 -38
  94. data/spec/data/samples/load_images.rb.txt +41 -5
  95. data/spec/data/samples/portrait-landscape.rb.txt +49 -51
  96. data/spec/data/samples/ranges.rb.txt +460 -429
  97. data/spec/data/samples/saves.rb.txt +801 -785
  98. data/spec/data/samples/showcase.rb.txt +5910 -5906
  99. data/spec/data/samples/text_options.rb.txt +1125 -981
  100. data/spec/data/samples/tgc_proofs.rb.txt +81 -79
  101. data/spec/data/samples/units.rb.txt +18 -12
  102. data/spec/data/xlsx/with_macros.xlsm +0 -0
  103. data/spec/graphics/cairo_context_wrapper_spec.rb +84 -75
  104. data/spec/graphics/graphics_images_spec.rb +94 -85
  105. data/spec/graphics/graphics_save_doc_spec.rb +67 -65
  106. data/spec/samples/expected/hand.png +0 -0
  107. data/spec/samples/expected/hand_pretty.png +0 -0
  108. data/spec/samples/expected/layout_00.png +0 -0
  109. data/spec/samples/expected/load_images_00.png +0 -0
  110. data/spec/samples/expected/ranges_00.png +0 -0
  111. data/spec/samples/expected/shape_00.png +0 -0
  112. data/spec/samples/expected/showcase.png +0 -0
  113. data/spec/samples/expected/showcase2.png +0 -0
  114. data/spec/samples/expected/showcase_individual_00.png +0 -0
  115. data/spec/samples/expected/showcase_individual_01.png +0 -0
  116. data/spec/samples/expected/showcase_individual_02.png +0 -0
  117. data/spec/samples/expected/showcase_individual_03.png +0 -0
  118. data/spec/samples/expected/text_00.png +0 -0
  119. data/spec/samples/expected/text_01.png +0 -0
  120. data/spec/samples/expected/text_02.png +0 -0
  121. data/spec/samples/samples_regression_spec.rb +82 -82
  122. data/spec/spec_helper.rb +3 -2
  123. data/squib.gemspec +48 -48
  124. data/squib.sublime-project +42 -36
  125. metadata +61 -33
  126. data/lib/squib/input_helpers.rb +0 -238
  127. data/spec/api/api_image_spec.rb +0 -38
  128. data/spec/api/api_text_spec.rb +0 -37
  129. data/spec/graphics/graphics_shapes_spec.rb +0 -85
  130. data/spec/graphics/graphics_text_spec.rb +0 -164
  131. data/spec/input_helpers_spec.rb +0 -238
  132. data/spec/samples/expected/embed_multi_00.png +0 -0
  133. data/spec/samples/expected/embed_multi_01.png +0 -0
  134. data/spec/samples/expected/embed_multi_02.png +0 -0
  135. data/spec/samples/expected/ranges_01.png +0 -0
  136. data/spec/samples/expected/ranges_02.png +0 -0
@@ -1,50 +1,57 @@
1
- require 'spec_helper'
2
-
3
- describe Squib::Deck do
4
- context '#csv' do
5
- it 'loads basic csv data' do
6
- expect(Squib.csv(file: csv_file('basic.csv'))).to eq({
7
- 'h1' => [1, 3],
8
- 'h2' => [2, 4]
9
- })
10
- end
11
-
12
- it 'collapses duplicate columns and warns' do
13
- expect(Squib.logger).to receive(:warn)
14
- .with('CSV duplicated the following column keys: h1,h1')
15
- expect(Squib.csv(file: csv_file('dup_cols.csv'))).to eq({
16
- 'h1' => [1, 3],
17
- 'h2' => [5, 7],
18
- 'H2' => [6, 8],
19
- 'h3' => [9, 10],
20
- })
21
- end
22
-
23
- it 'handles spaces properly' do
24
- expect(Squib.csv(file: csv_file('with_spaces.csv'))).to eq({
25
- 'With Spaces' => ['a b c ', 3],
26
- 'h2' => [2, 4],
27
- 'h3' => [3, nil]
28
- })
29
- end
30
- end
31
-
32
- context '#xlsx' do
33
- it 'loads basic xlsx data' do
34
- expect(Squib.xlsx(file: xlsx_file('basic.xlsx'))).to eq({
35
- 'Name' => %w(Larry Curly Mo),
36
- 'General Number' => %w(1 2 3), #general types always get loaded as strings with no conversion
37
- 'Actual Number' => [4.0, 5.0, 6.0], #numbers get auto-converted to integers
38
- })
39
- end
40
-
41
- it 'loads xlsx with formulas' do
42
- expect(Squib.xlsx(file: xlsx_file('formulas.xlsx'))).to eq({
43
- 'A' => %w(1 2),
44
- 'B' => %w(3 4),
45
- 'Sum' => %w(4 6),
46
- })
47
- end
48
-
49
- end
50
- end
1
+ require 'spec_helper'
2
+
3
+ describe Squib::Deck do
4
+ context '#csv' do
5
+ it 'loads basic csv data' do
6
+ expect(Squib.csv(file: csv_file('basic.csv'))).to eq({
7
+ 'h1' => [1, 3],
8
+ 'h2' => [2, 4]
9
+ })
10
+ end
11
+
12
+ it 'collapses duplicate columns and warns' do
13
+ expect(Squib.logger).to receive(:warn)
14
+ .with('CSV duplicated the following column keys: h1,h1')
15
+ expect(Squib.csv(file: csv_file('dup_cols.csv'))).to eq({
16
+ 'h1' => [1, 3],
17
+ 'h2' => [5, 7],
18
+ 'H2' => [6, 8],
19
+ 'h3' => [9, 10],
20
+ })
21
+ end
22
+
23
+ it 'handles spaces properly' do
24
+ expect(Squib.csv(file: csv_file('with_spaces.csv'))).to eq({
25
+ 'With Spaces' => ['a b c ', 3],
26
+ 'h2' => [2, 4],
27
+ 'h3' => [3, nil]
28
+ })
29
+ end
30
+ end
31
+
32
+ context '#xlsx' do
33
+ it 'loads basic xlsx data' do
34
+ expect(Squib.xlsx(file: xlsx_file('basic.xlsx'))).to eq({
35
+ 'Name' => %w(Larry Curly Mo),
36
+ 'General Number' => %w(1 2 3), #general types always get loaded as strings with no conversion
37
+ 'Actual Number' => [4.0, 5.0, 6.0], #numbers get auto-converted to integers
38
+ })
39
+ end
40
+
41
+ it 'loads xlsx with formulas' do
42
+ expect(Squib.xlsx(file: xlsx_file('formulas.xlsx'))).to eq({
43
+ 'A' => %w(1 2),
44
+ 'B' => %w(3 4),
45
+ 'Sum' => %w(4 6),
46
+ })
47
+ end
48
+
49
+ it 'loads xlsm files with macros' do
50
+ expect(Squib.xlsx(file: xlsx_file('with_macros.xlsm'))).to eq({
51
+ 'foo' => %w(8 10),
52
+ 'bar' => %w(9 11),
53
+ })
54
+ end
55
+
56
+ end
57
+ end
@@ -1,18 +1,38 @@
1
- require 'spec_helper'
2
-
3
- describe Squib::Deck do
4
-
5
- context '#hint' do
6
-
7
- it 'sets hinting to conf' do
8
- mock_conf = double(Squib::Conf)
9
- expect(mock_conf).to receive(:text_hint=).with(:cyan).once
10
- Squib::Deck.new do
11
- @conf = mock_conf
12
- hint text: :cyan
13
- end
14
- end
15
-
16
- end
17
-
1
+ require 'spec_helper'
2
+
3
+ describe Squib::Deck do
4
+
5
+ context '#hint' do
6
+
7
+ it 'sets hinting to conf' do
8
+ mock_conf = double(Squib::Conf)
9
+ expect(mock_conf).to receive(:text_hint=).with(:cyan).once
10
+ Squib::Deck.new do
11
+ @conf = mock_conf
12
+ hint text: :cyan
13
+ end
14
+ end
15
+
16
+ end
17
+
18
+ context '#set' do
19
+
20
+ it 'puts font in @font' do
21
+ deck = Squib::Deck.new do
22
+ set font: 'foo'
23
+ end
24
+ expect(deck.font).to eq ('foo')
25
+ end
26
+
27
+ it 'raises deprecation errors on img_dir' do
28
+ set_img_dir = Proc.new do
29
+ Squib::Deck.new do
30
+ set img_dir: 'foo'
31
+ end
32
+ end
33
+ expect { set_img_dir.call }.to raise_error('DEPRECATED: As of v0.7 img_dir is no longer supported in "set". Use config.yml instead.')
34
+ end
35
+
36
+ end
37
+
18
38
  end
@@ -0,0 +1,127 @@
1
+ require 'spec_helper'
2
+ require 'squib/args/box'
3
+
4
+ describe Squib::Args::Box do
5
+ subject(:box) { Squib::Args::Box.new }
6
+ let(:expected_defaults) { {x: [0], y: [0], width: [:deck], height: [:deck] } }
7
+
8
+ it 'intitially has no params set' do
9
+ expect(box).not_to respond_to(:x, :y, :width, :height)
10
+ end
11
+
12
+ it 'extracts the defaults from Box on an empty hash' do
13
+ box.load!({})
14
+ expect(box).to have_attributes(expected_defaults)
15
+ end
16
+
17
+ it 'extracts what is specified and fills in defaults from Box' do
18
+ box.load!(x: 4, width: 40)
19
+ expect(box).to have_attributes(x: [4], width: [40], y: [0], height: [:deck])
20
+ end
21
+
22
+ it 'extracts the defaults from Box on an empty hash' do
23
+ box.load!({foo: :bar})
24
+ expect(box).to have_attributes(expected_defaults)
25
+ expect(box).not_to respond_to(:foo)
26
+ end
27
+
28
+ context 'single expansion' do
29
+ let(:args) { {x: [1, 2], y: 3} }
30
+ before(:each) { box.load!(args, expand_by: 2) }
31
+ it 'expands box' do
32
+ expect(box).to have_attributes({
33
+ x: [1, 2],
34
+ y: [3, 3],
35
+ height: [:deck, :deck],
36
+ width: [:deck, :deck]
37
+ })
38
+ end
39
+
40
+ it 'gives access to each card too' do
41
+ expect(box[0]).to have_attributes({
42
+ x: 1,
43
+ y: 3,
44
+ height: :deck,
45
+ width: :deck
46
+ })
47
+ end
48
+ end
49
+
50
+ context 'layouts' do
51
+ let(:layout) do
52
+ { 'attack' => { 'x' => 50 },
53
+ 'defend' => { 'x' => 60 } }
54
+ end
55
+
56
+ it 'are used when not specified' do
57
+ args = { layout: ['attack', 'defend'] }
58
+ box.load!(args, expand_by: 2, layout: layout)
59
+ expect(box).to have_attributes(
60
+ x: [50, 60], # set by layout
61
+ y: [0, 0], # Box default
62
+ )
63
+ end
64
+
65
+ it 'handle single expansion' do
66
+ args = { layout: 'attack' }
67
+ box.load!(args, expand_by: 2, layout: layout)
68
+ expect(box).to have_attributes(
69
+ x: [50, 50], # set by layout
70
+ y: [0, 0], # Box default
71
+ )
72
+ end
73
+
74
+ it 'handles symbols' do
75
+ args = { layout: :attack }
76
+ box.load!(args, expand_by: 2, layout: layout)
77
+ expect(box).to have_attributes(
78
+ x: [50, 50], # set by layout
79
+ y: [0, 0], # Box default
80
+ )
81
+ end
82
+
83
+ it 'warns on non-existent layouts' do
84
+ args = { layout: :heal}
85
+ expect(Squib.logger).to receive(:warn).with('Layout "heal" does not exist in layout file - using default instead').at_least(:once)
86
+ box.load!(args, expand_by: 2, layout: layout)
87
+ expect(box).to have_attributes(
88
+ x: [0, 0], # Box default
89
+ y: [0, 0], # Box default
90
+ )
91
+ end
92
+ end
93
+
94
+ context 'unit conversion' do
95
+
96
+ it 'converts units on all args' do
97
+ args = {x: ['1in', '2in'], y: 300, width: '1in', height: '1in'}
98
+ box.load!(args, expand_by: 2)
99
+ expect(box).to have_attributes(
100
+ x: [300, 600],
101
+ y: [300, 300],
102
+ width: [300, 300],
103
+ height: [300, 300],
104
+ )
105
+ end
106
+
107
+ end
108
+
109
+ context 'validation' do
110
+ it 'replaces with deck width and height' do
111
+ args = {width: :deck, height: :deck}
112
+ deck = OpenStruct.new(width: 123, height: 456)
113
+ box = Squib::Args::Box.new(deck)
114
+ box.load!(args, expand_by: 1)
115
+ expect(box).to have_attributes(width: [123], height: [456])
116
+ end
117
+
118
+ it 'has radius override x_radius and y_radius' do
119
+ args = {x_radius: 1, y_radius: 2, radius: 3}
120
+ box.load!(args, expand_by: 2)
121
+ expect(box).to have_attributes(x_radius: [3, 3], y_radius: [3, 3])
122
+ end
123
+
124
+ end
125
+
126
+
127
+ end
@@ -0,0 +1,95 @@
1
+ require 'spec_helper'
2
+ require 'squib/args/draw'
3
+
4
+ describe Squib::Args::Draw do
5
+ let(:custom_colors) { {'foo' => 'abc'} }
6
+ subject(:draw) {Squib::Args::Draw.new(custom_colors)}
7
+
8
+ context 'unit conversion' do
9
+
10
+ it 'converts units on stroke width' do
11
+ args = {stroke_width: '2in'}
12
+ draw.load!(args, expand_by: 2)
13
+ expect(draw).to have_attributes(stroke_width: [600, 600])
14
+ end
15
+
16
+ end
17
+
18
+ context 'dsl overrides' do
19
+ subject(:draw) {Squib::Args::Draw.new(custom_colors, {stroke_width: 0.0})}
20
+
21
+ it 'works when specified' do
22
+ draw.load!({}) # go right to defaults
23
+ expect(draw.stroke_width).to eq( [0.0] ) #ordinarily a non-zero according
24
+ end
25
+
26
+ end
27
+
28
+ context 'validation' do
29
+
30
+ it 'converts to Cairo options' do
31
+ args = {join: 'bevel', cap: 'round'}
32
+ draw.load!(args)
33
+ expect(draw).to have_attributes(
34
+ join: [Cairo::LINE_JOIN_BEVEL],
35
+ cap: [Cairo::LINE_JOIN_ROUND]
36
+ )
37
+ end
38
+
39
+ it 'parses dash options' do
40
+ args = {dash: '3 4 5'}
41
+ draw.load!(args)
42
+ expect(draw).to have_attributes(dash: [[3, 4, 5]])
43
+ end
44
+
45
+ it 'parses more complex dash options' do
46
+ args = {dash: '30.5, 90, 5'}
47
+ draw.load!(args)
48
+ expect(draw).to have_attributes(dash: [[30.5, 90, 5]])
49
+ end
50
+
51
+ it 'does unit conversion on dash options' do
52
+ args = {dash: '3in 4in 5in'}
53
+ draw.load!(args)
54
+ expect(draw).to have_attributes(dash: [[900, 1200, 1500]])
55
+ end
56
+
57
+ it 'converts line caps to Cairo constants' do
58
+ args = {cap: :SQUARE}
59
+ draw.load! args
60
+ expect(draw).to have_attributes( cap: [Cairo::LINE_CAP_SQUARE] )
61
+ end
62
+
63
+ it 'allows fill_first stroke_strategy' do
64
+ args = {stroke_strategy: :FILL_first}
65
+ draw.load! args
66
+ expect(draw).to have_attributes( stroke_strategy: [:fill_first] )
67
+ end
68
+
69
+ it 'allows stroke_first stroke_strategy' do
70
+ args = {stroke_strategy: ' stroke_FIRST '}
71
+ draw.load! args
72
+ expect(draw).to have_attributes( stroke_strategy: [:stroke_first] )
73
+ end
74
+
75
+ it 'disallows anything not stroke_first and fill_first' do
76
+ args = {stroke_strategy: 'foo'}
77
+ expect { draw.load! args }.to raise_error("Only 'stroke_first' or 'fill_first' allowed")
78
+ end
79
+
80
+ context 'custom colors' do
81
+
82
+ it 'looks up custom colors in the config' do
83
+ draw.load!({color: 'foo'})
84
+ expect(draw.color).to eq ['abc']
85
+ end
86
+
87
+ it 'passes on through for non-custom color' do
88
+ draw = Squib::Args::Draw.new(custom_colors)
89
+ draw.load!({color: 'bar'})
90
+ expect(draw.color).to eq ['bar']
91
+ end
92
+
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+ require 'squib/args/embed_key'
3
+
4
+ describe Squib::Args::EmbedKey do
5
+
6
+ context '#validate_key' do
7
+
8
+ it 'converts to string' do
9
+ expect(subject.validate_key(2.5)).to eq ('2.5')
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+ require 'squib/args/input_file'
3
+
4
+ describe Squib::Args::InputFile do
5
+ subject(:ifile) {Squib::Args::InputFile.new}
6
+
7
+ context 'validate_file' do
8
+
9
+ it 'allows a file if it exists' do
10
+ args = {file: __FILE__} # I code therefore I am.
11
+ ifile.load!(args, expand_by: 1)
12
+ expect(ifile).to have_attributes(file: [File.expand_path(__FILE__)])
13
+ end
14
+
15
+ it 'raises on non-existent file' do
16
+ args = {file: 'foo.rb'}
17
+ expect { ifile.load!(args, expand_by: 1) }.to raise_error("File #{File.expand_path('foo.rb')} does not exist!")
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+ require 'squib/args/paint'
3
+
4
+ describe Squib::Args::Draw do
5
+ let(:custom_colors) { {'foo' => 'abc'} }
6
+ subject(:paint) {Squib::Args::Paint.new(custom_colors)}
7
+
8
+ context 'alpha' do
9
+
10
+ it 'can be a float' do
11
+ args = {alpha: 0.6}
12
+ paint.load!(args)
13
+ expect(paint.alpha).to eq [0.6]
14
+ end
15
+
16
+ it 'raises exception when not a float' do
17
+ args = {alpha: /6/}
18
+ expect { paint.load!(args) }.to raise_error('alpha must respond to to_f')
19
+ end
20
+
21
+ end
22
+ end