squib 0.8.0 → 0.9.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 (140) hide show
  1. checksums.yaml +4 -4
  2. data/.gitmodules +14 -0
  3. data/.travis.yml +4 -0
  4. data/CHANGELOG.md +201 -175
  5. data/Gemfile +2 -4
  6. data/README.md +650 -645
  7. data/RELEASE TODO.md +18 -18
  8. data/Rakefile +106 -99
  9. data/appveyor.yml +29 -0
  10. data/lib/squib.rb +32 -32
  11. data/lib/squib/api/background.rb +20 -20
  12. data/lib/squib/api/data.rb +131 -131
  13. data/lib/squib/api/image.rb +108 -90
  14. data/lib/squib/api/save.rb +151 -149
  15. data/lib/squib/api/settings.rb +35 -35
  16. data/lib/squib/api/shapes.rb +255 -230
  17. data/lib/squib/api/text.rb +65 -65
  18. data/lib/squib/api/text_embed.rb +96 -96
  19. data/lib/squib/args/arg_loader.rb +138 -138
  20. data/lib/squib/args/box.rb +54 -54
  21. data/lib/squib/args/card_range.rb +32 -32
  22. data/lib/squib/args/color_validator.rb +11 -11
  23. data/lib/squib/args/coords.rb +32 -32
  24. data/lib/squib/args/dir_validator.rb +16 -16
  25. data/lib/squib/args/draw.rb +92 -92
  26. data/lib/squib/args/embed_adjust.rb +25 -25
  27. data/lib/squib/args/embed_key.rb +17 -17
  28. data/lib/squib/args/hand_special.rb +37 -37
  29. data/lib/squib/args/import.rb +39 -39
  30. data/lib/squib/args/input_file.rb +37 -37
  31. data/lib/squib/args/paint.rb +43 -43
  32. data/lib/squib/args/paragraph.rb +116 -115
  33. data/lib/squib/args/save_batch.rb +63 -60
  34. data/lib/squib/args/scale_box.rb +53 -53
  35. data/lib/squib/args/sheet.rb +72 -72
  36. data/lib/squib/args/showcase_special.rb +38 -38
  37. data/lib/squib/args/svg_special.rb +37 -37
  38. data/lib/squib/args/transform.rb +60 -24
  39. data/lib/squib/args/typographer.rb +117 -117
  40. data/lib/squib/card.rb +66 -67
  41. data/lib/squib/conf.rb +131 -117
  42. data/lib/squib/constants.rb +12 -178
  43. data/lib/squib/deck.rb +113 -113
  44. data/lib/squib/graphics/cairo_context_wrapper.rb +113 -99
  45. data/lib/squib/graphics/gradient_regex.rb +46 -46
  46. data/lib/squib/graphics/hand.rb +42 -42
  47. data/lib/squib/graphics/image.rb +103 -76
  48. data/lib/squib/graphics/save_doc.rb +103 -103
  49. data/lib/squib/graphics/save_images.rb +39 -33
  50. data/lib/squib/graphics/shapes.rb +135 -119
  51. data/lib/squib/graphics/showcase.rb +85 -85
  52. data/lib/squib/graphics/text.rb +176 -176
  53. data/lib/squib/layout_parser.rb +91 -91
  54. data/lib/squib/layouts/economy.yml +85 -85
  55. data/lib/squib/layouts/fantasy.yml +101 -101
  56. data/lib/squib/layouts/hand.yml +62 -62
  57. data/lib/squib/layouts/playing-card.yml +35 -35
  58. data/lib/squib/layouts/tuck_box.yml +45 -45
  59. data/lib/squib/project_template/IDEAS.md +22 -0
  60. data/lib/squib/project_template/PLAYTESTING.md +26 -0
  61. data/lib/squib/project_template/RULES.md +21 -0
  62. data/lib/squib/project_template/config.yml +49 -45
  63. data/lib/squib/sample_helpers.rb +34 -0
  64. data/lib/squib/version.rb +10 -10
  65. data/samples/autoscale_font/_autoscale_font.rb +29 -0
  66. data/samples/color_shortcuts.rb +6 -6
  67. data/samples/csv_import.rb +26 -26
  68. data/samples/custom-config.yml +5 -5
  69. data/samples/custom_config.rb +18 -18
  70. data/samples/draw_shapes.rb +48 -45
  71. data/samples/embed_text.rb +88 -88
  72. data/samples/excel.rb +55 -55
  73. data/samples/hand.rb +24 -24
  74. data/samples/images/_images.rb +104 -0
  75. data/samples/intro/01_hello.rb +9 -0
  76. data/samples/intro/02_options.rb +15 -0
  77. data/samples/intro/03_layout.rb +12 -0
  78. data/samples/intro/04_arrays.rb +16 -0
  79. data/samples/intro/05_excel.rb +15 -0
  80. data/samples/layouts.rb +62 -62
  81. data/samples/layouts_builtin.rb +51 -51
  82. data/samples/load_images.rb +99 -78
  83. data/samples/load_images_config.yml +1 -0
  84. data/samples/quantity_explosion.csv +2 -2
  85. data/samples/ranges.rb +64 -64
  86. data/samples/sample.csv +2 -2
  87. data/samples/saves.rb +9 -1
  88. data/samples/sprites.png +0 -0
  89. data/samples/text/_text.rb +46 -0
  90. data/samples/text_options.rb +102 -102
  91. data/spec/api/api_data_spec.rb +117 -117
  92. data/spec/api/api_settings_spec.rb +37 -37
  93. data/spec/args/box_spec.rb +127 -127
  94. data/spec/args/draw_spec.rb +101 -95
  95. data/spec/args/embed_key_spec.rb +13 -13
  96. data/spec/args/input_file_spec.rb +21 -21
  97. data/spec/args/paint_spec.rb +21 -21
  98. data/spec/args/paragraph_spec.rb +152 -152
  99. data/spec/args/range_spec.rb +40 -40
  100. data/spec/args/save_batch_spec.rb +51 -51
  101. data/spec/args/scale_box_spec.rb +71 -71
  102. data/spec/args/sheet_spec.rb +58 -58
  103. data/spec/args/showcase_special_spec.rb +15 -15
  104. data/spec/args/transform_spec.rb +25 -0
  105. data/spec/card_spec.rb +11 -0
  106. data/spec/conf_spec.rb +13 -3
  107. data/spec/data/conf/unrecognized.yml +4 -0
  108. data/spec/data/csv/qty.csv +2 -2
  109. data/spec/data/csv/qty_named.csv +2 -2
  110. data/spec/data/csv/with_spaces.csv +2 -2
  111. data/spec/data/samples/autoscale_font.rb.txt +84 -84
  112. data/spec/data/samples/basic.rb.txt +227 -209
  113. data/spec/data/samples/config_text_markup.rb.txt +72 -72
  114. data/spec/data/samples/csv_import.rb.txt +213 -213
  115. data/spec/data/samples/custom_config.rb.txt +57 -48
  116. data/spec/data/samples/draw_shapes.rb.txt +555 -3
  117. data/spec/data/samples/embed_text.rb.txt +283 -283
  118. data/spec/data/samples/excel.rb.txt +661 -661
  119. data/spec/data/samples/gradients.rb.txt +77 -79
  120. data/spec/data/samples/hand.rb.txt +538 -538
  121. data/spec/data/samples/hello_world.rb.txt +36 -36
  122. data/spec/data/samples/load_images.rb.txt +170 -0
  123. data/spec/data/samples/portrait-landscape.rb.txt +51 -49
  124. data/spec/data/samples/ranges.rb.txt +472 -460
  125. data/spec/data/samples/saves.rb.txt +810 -801
  126. data/spec/data/samples/showcase.rb.txt +5926 -5910
  127. data/spec/data/samples/text_options.rb.txt +1125 -1125
  128. data/spec/data/samples/tgc_proofs.rb.txt +95 -81
  129. data/spec/graphics/cairo_context_wrapper_spec.rb +104 -84
  130. data/spec/graphics/graphics_save_doc_spec.rb +67 -67
  131. data/spec/samples/diff-with-css.example.html +39 -0
  132. data/spec/samples/expected/load_images_00.png +0 -0
  133. data/spec/samples/expected/shape_00.png +0 -0
  134. data/spec/samples/run_samples_spec.rb +17 -0
  135. data/spec/samples/samples_regression_spec.rb +72 -82
  136. data/spec/spec_helper.rb +9 -1
  137. data/squib.gemspec +49 -48
  138. data/squib.sublime-project +42 -42
  139. metadata +94 -48
  140. data/spec/graphics/graphics_images_spec.rb +0 -94
@@ -1,37 +1,37 @@
1
- require 'squib/args/arg_loader'
2
-
3
- module Squib
4
- # @api private
5
- module Args
6
-
7
- class SvgSpecial
8
- include ArgLoader
9
-
10
- def self.parameters
11
- { data: nil, id: nil, force_id: false }
12
- end
13
-
14
- def self.expanding_parameters
15
- parameters.keys # all of them
16
- end
17
-
18
- def self.params_with_units
19
- []
20
- end
21
-
22
- def validate_id(arg, _i)
23
- return nil if arg.nil?
24
- arg = '#' << arg unless arg.start_with? '#'
25
- arg
26
- end
27
-
28
- # Only render if we have an ID specified, or we are forcing an ID
29
- def render?(i)
30
- return false if force_id[i] && id[i].to_s.empty?
31
- return true
32
- end
33
-
34
- end
35
-
36
- end
37
- end
1
+ require 'squib/args/arg_loader'
2
+
3
+ module Squib
4
+ # @api private
5
+ module Args
6
+
7
+ class SvgSpecial
8
+ include ArgLoader
9
+
10
+ def self.parameters
11
+ { data: nil, id: nil, force_id: false }
12
+ end
13
+
14
+ def self.expanding_parameters
15
+ parameters.keys # all of them
16
+ end
17
+
18
+ def self.params_with_units
19
+ []
20
+ end
21
+
22
+ def validate_id(arg, _i)
23
+ return nil if arg.nil?
24
+ arg = '#' << arg unless arg.start_with? '#'
25
+ arg
26
+ end
27
+
28
+ # Only render if we have an ID specified, or we are forcing an ID
29
+ def render?(i)
30
+ return false if force_id[i] && id[i].to_s.empty?
31
+ return true
32
+ end
33
+
34
+ end
35
+
36
+ end
37
+ end
@@ -1,25 +1,61 @@
1
- require 'squib/args/arg_loader'
2
-
3
- module Squib
4
- # @api private
5
- module Args
6
-
7
- class Transform
8
- include ArgLoader
9
-
10
- def self.parameters
11
- { angle: 0 }
12
- end
13
-
14
- def self.expanding_parameters
15
- parameters.keys # all of them
16
- end
17
-
18
- def self.params_with_units
19
- parameters.keys # all of them
20
- end
21
-
22
- end
23
-
24
- end
1
+ require 'squib/args/arg_loader'
2
+
3
+ module Squib
4
+ # @api private
5
+ module Args
6
+
7
+ class Transform
8
+ include ArgLoader
9
+
10
+ def initialize(deck = nil)
11
+ @deck = deck
12
+ end
13
+
14
+ def self.parameters
15
+ { angle: 0,
16
+ crop_x: 0,
17
+ crop_y: 0,
18
+ crop_width: :native,
19
+ crop_height: :native,
20
+ crop_corner_radius: nil,
21
+ crop_corner_x_radius: 0,
22
+ crop_corner_y_radius: 0,
23
+ flip_vertical: false,
24
+ flip_horizontal: false,
25
+ }
26
+ end
27
+
28
+ def self.expanding_parameters
29
+ parameters.keys # all of them
30
+ end
31
+
32
+ def self.params_with_units
33
+ parameters.keys - [:flip_vertical, :flip_horizontal]
34
+ end
35
+
36
+ def validate_crop_width(arg, _i)
37
+ return arg if @deck.nil?
38
+ return @deck.width if arg == :deck
39
+ arg
40
+ end
41
+
42
+ def validate_crop_height(arg, _i)
43
+ return arg if @deck.nil?
44
+ return @deck.height if arg == :deck
45
+ arg
46
+ end
47
+
48
+ def validate_crop_corner_x_radius(arg, i)
49
+ return crop_corner_radius[i] unless crop_corner_radius[i].nil?
50
+ arg
51
+ end
52
+
53
+ def validate_crop_corner_y_radius(arg, i)
54
+ return crop_corner_radius[i] unless crop_corner_radius[i].nil?
55
+ arg
56
+ end
57
+
58
+ end
59
+
60
+ end
25
61
  end
@@ -1,118 +1,118 @@
1
- require 'squib/constants'
2
- module Squib
3
- #@api private
4
- module Args
5
- # Internal class for handling arguments
6
- #@api private
7
- class Typographer
8
-
9
- def initialize(config = Conf::DEFAULTS)
10
- %w(lsquote ldquote rsquote rdquote smart_quotes
11
- em_dash en_dash ellipsis).each do |var|
12
- instance_variable_set("@#{var}", config[var])
13
- end
14
- end
15
-
16
- def process(str)
17
- str = explicit_replacements(str.to_s)
18
- str = smart_quotes(str) if @smart_quotes
19
- str
20
- end
21
-
22
- def explicit_replacements(str)
23
- [ :left_curly, :right_curly, :apostraphize,
24
- :ellipsificate, :em_dash, :en_dash ].each do |sym|
25
- str = each_non_tag(str) do |token|
26
- self.method(sym).call(token)
27
- end
28
- end
29
- str
30
- end
31
-
32
- def smart_quotes(str)
33
- [ :single_inside_double_quote,
34
- :right_double_quote,
35
- :left_double_quote,
36
- :right_single_quote,
37
- :left_single_quote].each do |sym|
38
- str = each_non_tag(str) do |token|
39
- self.method(sym).call(token)
40
- end
41
- end
42
- str
43
- end
44
-
45
- # Iterate over each non-tag for processing
46
- # Allows us to ignore anything inside < and >
47
- def each_non_tag(str)
48
- full_str = ''
49
- tag_delimit = /(<(?:(?!<).)*>)/ # use non-capturing group w/ negative lookahead
50
- str.split(tag_delimit).each do |token|
51
- if token.start_with? '<'
52
- full_str << token # don't process tags
53
- else
54
- full_str << yield(token)
55
- end
56
- end
57
- return full_str
58
- end
59
-
60
- # Straightforward replace
61
- def left_curly(str)
62
- str.gsub('``', @ldquote)
63
- end
64
-
65
- # Straightforward replace
66
- def right_curly(str)
67
- str.gsub(%{''}, @rdquote)
68
- end
69
-
70
- # A quote between two letters is an apostraphe
71
- def apostraphize(str)
72
- str.gsub(/(\w)(\')(\w)/, '\1' + @rsquote + '\3')
73
- end
74
-
75
- # Straightforward replace
76
- def ellipsificate(str)
77
- str.gsub('...', @ellipsis)
78
- end
79
-
80
- # Straightforward replace
81
- def en_dash(str)
82
- str.gsub('--', @en_dash)
83
- end
84
-
85
- # Straightforward replace
86
- def em_dash(str)
87
- str.gsub('---', @em_dash)
88
- end
89
-
90
- # Quote next to non-whitespace curls
91
- def right_double_quote(str)
92
- str.gsub(/(\S)(\")/, '\1' + @rdquote)
93
- end
94
-
95
- # Quote next to non-whitespace curls
96
- def left_double_quote(str)
97
- str.gsub(/(\")(\S)/, @ldquote + '\2')
98
- end
99
-
100
- # Handle the cases where a double quote is next to a single quote
101
- def single_inside_double_quote(str)
102
- str.gsub(/(\")(\')(\S)/, @ldquote + @lsquote + '\3')
103
- .gsub(/(\")(\')(\S)/, '\1' + @rsquote + @rdquote)
104
- end
105
-
106
- # Quote next to non-whitespace curls
107
- def right_single_quote(str)
108
- str.gsub(/(\S)(\')/, '\1' + @rsquote)
109
- end
110
-
111
- # Quote next to non-whitespace curls
112
- def left_single_quote(str)
113
- str.gsub(/(\')(\S)/, @lsquote + '\2')
114
- end
115
-
116
- end
117
- end
1
+ require 'squib/constants'
2
+ module Squib
3
+ #@api private
4
+ module Args
5
+ # Internal class for handling arguments
6
+ #@api private
7
+ class Typographer
8
+
9
+ def initialize(config = Conf::DEFAULTS)
10
+ %w(lsquote ldquote rsquote rdquote smart_quotes
11
+ em_dash en_dash ellipsis).each do |var|
12
+ instance_variable_set("@#{var}", config[var])
13
+ end
14
+ end
15
+
16
+ def process(str)
17
+ str = explicit_replacements(str.to_s)
18
+ str = smart_quotes(str) if @smart_quotes
19
+ str
20
+ end
21
+
22
+ def explicit_replacements(str)
23
+ [ :left_curly, :right_curly, :apostraphize,
24
+ :ellipsificate, :em_dash, :en_dash ].each do |sym|
25
+ str = each_non_tag(str) do |token|
26
+ self.method(sym).call(token)
27
+ end
28
+ end
29
+ str
30
+ end
31
+
32
+ def smart_quotes(str)
33
+ [ :single_inside_double_quote,
34
+ :right_double_quote,
35
+ :left_double_quote,
36
+ :right_single_quote,
37
+ :left_single_quote].each do |sym|
38
+ str = each_non_tag(str) do |token|
39
+ self.method(sym).call(token)
40
+ end
41
+ end
42
+ str
43
+ end
44
+
45
+ # Iterate over each non-tag for processing
46
+ # Allows us to ignore anything inside < and >
47
+ def each_non_tag(str)
48
+ full_str = ''
49
+ tag_delimit = /(<(?:(?!<).)*>)/ # use non-capturing group w/ negative lookahead
50
+ str.split(tag_delimit).each do |token|
51
+ if token.start_with? '<'
52
+ full_str << token # don't process tags
53
+ else
54
+ full_str << yield(token)
55
+ end
56
+ end
57
+ return full_str
58
+ end
59
+
60
+ # Straightforward replace
61
+ def left_curly(str)
62
+ str.gsub('``', @ldquote)
63
+ end
64
+
65
+ # Straightforward replace
66
+ def right_curly(str)
67
+ str.gsub(%{''}, @rdquote)
68
+ end
69
+
70
+ # A quote between two letters is an apostraphe
71
+ def apostraphize(str)
72
+ str.gsub(/(\w)(\')(\w)/, '\1' + @rsquote + '\3')
73
+ end
74
+
75
+ # Straightforward replace
76
+ def ellipsificate(str)
77
+ str.gsub('...', @ellipsis)
78
+ end
79
+
80
+ # Straightforward replace
81
+ def en_dash(str)
82
+ str.gsub('--', @en_dash)
83
+ end
84
+
85
+ # Straightforward replace
86
+ def em_dash(str)
87
+ str.gsub('---', @em_dash)
88
+ end
89
+
90
+ # Quote next to non-whitespace curls
91
+ def right_double_quote(str)
92
+ str.gsub(/(\S)(\")/, '\1' + @rdquote)
93
+ end
94
+
95
+ # Quote next to non-whitespace curls
96
+ def left_double_quote(str)
97
+ str.gsub(/(\")(\S)/, @ldquote + '\2')
98
+ end
99
+
100
+ # Handle the cases where a double quote is next to a single quote
101
+ def single_inside_double_quote(str)
102
+ str.gsub(/(\")(\')(\S)/, @ldquote + @lsquote + '\3')
103
+ .gsub(/(\")(\')(\S)/, '\1' + @rsquote + @rdquote)
104
+ end
105
+
106
+ # Quote next to non-whitespace curls
107
+ def right_single_quote(str)
108
+ str.gsub(/(\S)(\')/, '\1' + @rsquote)
109
+ end
110
+
111
+ # Quote next to non-whitespace curls
112
+ def left_single_quote(str)
113
+ str.gsub(/(\')(\S)/, @lsquote + '\2')
114
+ end
115
+
116
+ end
117
+ end
118
118
  end
@@ -1,67 +1,66 @@
1
- require 'cairo'
2
- require 'squib/graphics/cairo_context_wrapper'
3
-
4
- module Squib
5
- # Back end graphics. Private.
6
- class Card
7
-
8
- # :nodoc:
9
- # @api private
10
- attr_reader :width, :height, :backend, :svgfile, :index
11
-
12
- # :nodoc:
13
- # @api private
14
- attr_accessor :cairo_surface, :cairo_context
15
-
16
- # :nodoc:
17
- # @api private
18
- def initialize(deck, width, height, index=-1)
19
- @deck = deck
20
- @width = width
21
- @height = height
22
- @backend = deck.backend
23
- @index = index
24
- @svgfile = "#{deck.dir}/#{deck.prefix}#{deck.count_format % index}.svg"
25
- @cairo_surface = make_surface(@svgfile, @backend)
26
- @cairo_context = Squib::Graphics::CairoContextWrapper.new(Cairo::Context.new(@cairo_surface))
27
- @cairo_context.antialias = deck.antialias
28
- end
29
-
30
- # :nodoc:
31
- # @api private
32
- def make_surface(svgfile, backend)
33
- case backend.downcase.to_sym
34
- when :memory
35
- Cairo::ImageSurface.new(@width, @height)
36
- when :svg
37
- Dir.mkdir @deck.dir unless Dir.exists?(@deck.dir)
38
- Cairo::SVGSurface.new(svgfile, @width, @height)
39
- else
40
- Squib.logger.fatal "Back end not recognized: '#{backend}'"
41
- abort
42
- end
43
- end
44
-
45
-
46
- # A save/restore wrapper for using Cairo
47
- # :nodoc:
48
- # @api private
49
- def use_cairo(&block)
50
- @cairo_context.save
51
- block.yield(@cairo_context)
52
- @cairo_context.restore
53
- end
54
-
55
- ########################
56
- ### BACKEND GRAPHICS ###
57
- ########################
58
- require 'squib/graphics/background'
59
- require 'squib/graphics/image'
60
- require 'squib/graphics/save_doc'
61
- require 'squib/graphics/save_images'
62
- require 'squib/graphics/shapes'
63
- require 'squib/graphics/showcase'
64
- require 'squib/graphics/text'
65
-
66
- end
67
- end
1
+ require 'cairo'
2
+ require 'squib/graphics/cairo_context_wrapper'
3
+
4
+ module Squib
5
+ # Back end graphics. Private.
6
+ class Card
7
+
8
+ # :nodoc:
9
+ # @api private
10
+ attr_reader :width, :height, :backend, :svgfile, :index
11
+
12
+ # :nodoc:
13
+ # @api private
14
+ attr_accessor :cairo_surface, :cairo_context
15
+
16
+ # :nodoc:
17
+ # @api private
18
+ def initialize(deck, width, height, index=-1)
19
+ @deck = deck
20
+ @width = width
21
+ @height = height
22
+ @backend = deck.backend
23
+ @index = index
24
+ @svgfile = "#{deck.dir}/#{deck.prefix}#{deck.count_format % index}.svg"
25
+ @cairo_surface = make_surface(@svgfile, @backend)
26
+ @cairo_context = Squib::Graphics::CairoContextWrapper.new(Cairo::Context.new(@cairo_surface))
27
+ @cairo_context.antialias = deck.antialias
28
+ end
29
+
30
+ # :nodoc:
31
+ # @api private
32
+ def make_surface(svgfile, backend)
33
+ case backend.downcase.to_sym
34
+ when :memory
35
+ Cairo::ImageSurface.new(@width, @height)
36
+ when :svg
37
+ Dir.mkdir @deck.dir unless Dir.exists?(@deck.dir)
38
+ Cairo::SVGSurface.new(svgfile, @width, @height)
39
+ else
40
+ Squib.logger.fatal "Back end not recognized: '#{backend}'"
41
+ abort
42
+ end
43
+ end
44
+
45
+ # A save/restore wrapper for using Cairo
46
+ # :nodoc:
47
+ # @api private
48
+ def use_cairo(&block)
49
+ @cairo_context.save
50
+ block.yield(@cairo_context)
51
+ @cairo_context.restore
52
+ end
53
+
54
+ ########################
55
+ ### BACKEND GRAPHICS ###
56
+ ########################
57
+ require 'squib/graphics/background'
58
+ require 'squib/graphics/image'
59
+ require 'squib/graphics/save_doc'
60
+ require 'squib/graphics/save_images'
61
+ require 'squib/graphics/shapes'
62
+ require 'squib/graphics/showcase'
63
+ require 'squib/graphics/text'
64
+
65
+ end
66
+ end