zebra-zpl 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 02d6f5e561ffabed62717502d3f762fa518bfd00
4
+ data.tar.gz: 3bcba1f5caedeebf16bea8e9018021f116644378
5
+ SHA512:
6
+ metadata.gz: 3e3fd2f85335014ff4afe6350aef68752fd7dd318a4c02e1823a55620361e2e571626708b227e096274cb38540cced96c326b13add7b51e6fca8819dd7bdf7f4
7
+ data.tar.gz: e5dad045be5b3eb38bb74749f3c3eabb7196f1da24b1c5e3f5a4f091f4a0e1c5694c8a06832f5ad58d8faf9a6899f39ef987954d79c08597b01568a90ebf3e8a
data/.gitignore ADDED
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ tags
19
+ bin
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in zebra-zpl.gemspec
4
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,11 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard 'rspec', cmd: "bundle exec rspec" do
5
+ watch(%r{^spec/.+_spec\.rb$})
6
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
7
+ watch('spec/spec_helper.rb') { "spec" }
8
+
9
+ watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
10
+ end
11
+
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 bulpettb
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Cássio Marques
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,180 @@
1
+ #### This is a gem based on a terrific older gem by Cassio Marques. Although the new printers are mostly compatible with old Eltron (Epl) code, my needs require many of the new Zebra (ZPL) functions.
2
+
3
+ # Zebra::Zpl
4
+
5
+ ### ToDo: Update documentation with instructions for new features such as font sizing, margins, and text alignment
6
+
7
+ Zebra::Zpl offers a Ruby DSL to design and print labels using the ZPL programming language.
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ gem 'zebra-zpl'
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install zebra-zpl
22
+
23
+ ## Usage
24
+
25
+ ### Building labels
26
+
27
+ You create new labels with an instance of the `Zebra::Zpl::Label` class. It accepts the following options:
28
+
29
+ * `copies`: The number of copies to print. This option defaults to 1.
30
+ * `width`: The label's width, in dots.
31
+ * `length`: The label's length, is dots.
32
+ * `gap`: The gap between labels, in dots.
33
+ * `print_speed`: The print speed to be used. You can use values between 0 and 6. This option is required.
34
+ * `print_density`: The print density to be used. You can use values between 0 and 15. This option is required.
35
+
36
+ With a label, you can start adding elements to it:
37
+
38
+ label = Zebra::Zpl::Label.new :print_density => 8, :print_speed => 3
39
+ text = Zebra::Zpl::Text.new :data => "Hello, printer!", :position => [100, 100], :font_size => Zebra::Zpl::FontSize::SIZE_2
40
+ label << text
41
+
42
+ You can add as many elements as you want.
43
+
44
+ ### Printing the labels
45
+
46
+ You need to have your printer visible to CUPS. Once your printer is configured and you know its name on CUPS, you can send the labels to the printer using a `Zebra::PrintJob` instance.
47
+
48
+ label = Zebra::Zpl::Label.new(
49
+ :width => 200,
50
+ :length => 200,
51
+ :print_speed => 3,
52
+ :print_density => 6
53
+ )
54
+
55
+
56
+ barcode = Zebra::Zpl::Barcode.new(
57
+ :data => "12345678",
58
+ :position => [50, 50],
59
+ :height => 50,
60
+ :print_human_readable_code => true,
61
+ :narrow_bar_width => 4,
62
+ :wide_bar_width => 8,
63
+ :type => Zebra::Zpl::BarcodeType::CODE_128_AUTO
64
+ )
65
+
66
+ label << barcode
67
+
68
+ print_job = Zebra::PrintJob.new "your-printer-name-on-cups"
69
+
70
+ print_job.print label
71
+
72
+ This will persist the label contents to a tempfile (using Ruby's tempfile core library) and copy the file to the printer using either `lpr -P <your-printer-name-on-cups> -o raw <path-to-the-temp-file>` (if you're on Mac OSX) or `lp -d <your-printer-name-on-cups> -o raw <path-to-the-tempfile>` (if you're on Linux). All the tempfile creation/path resolution, as well as which command has to be used, are handled by the `PrintJob` class.
73
+
74
+ ### Printing QR codes
75
+
76
+ label = Zebra::Zpl::Label.new(
77
+ :width=>350,
78
+ :length=>250,
79
+ :print_speed=>3,
80
+ :print_density=>6
81
+ )
82
+
83
+ qrcode = Zebra::Zpl::Qrcode.new(
84
+ :data=>"www.github.com",
85
+ :position=>[50,10],
86
+ :scale_factor=>3,
87
+ :correction_level=>"H"
88
+ )
89
+
90
+ label << qrcode
91
+
92
+ print_job = Zebra::PrintJob.new "your-qr-printer-name-on-cups"
93
+
94
+ print_job.print label
95
+
96
+ ### Available elements
97
+
98
+ #### Text
99
+
100
+ You create text elements to print using instances of the `Zebra::Zpl::Text` class. It accepts the following options:
101
+
102
+ * `position`: An array with the coordinates to place the text, in dots.
103
+ * `rotation`: The rotation for the text. More about the possible values below.
104
+ * `data`: The text to be printed.
105
+ * `v_multiplier`: The vertical multiplier to use.
106
+ * `h_multiplier`: The horizontal multipler to use.
107
+ * `print_mode`: The print mode. Can be normal ("N") or reverse ("R").
108
+ * `font_size`: The font size to use. You can use values between 1 and 5.
109
+
110
+ For the print modes, you can also use the constants:
111
+
112
+ * `Zebra::Zpl::PrintMode::NORMAL`
113
+ * `Zebra::Zpl::PrintMode::REVERSE`
114
+
115
+
116
+ #### Barcodes
117
+
118
+ You create barcode elements to print using instances of the `Zebra::Zpl::Barcode` class. It accepts the following options:
119
+
120
+ * `position`: An array with the coordinates to place the text, in dots.
121
+ * `height`: The barcode's height, in dots.
122
+ * `rotation`: The rotation for the text. More about the possible values below.
123
+ * `data`: The text to be printed.
124
+ * `type`: The type os barcode to use. More on the available types below.
125
+ * `narrow_bar_width`: The barcode's narrow bar width, in dots.
126
+ * `wide_bar_width`: The barcode's wide bar width, in dots.
127
+ * `print_human_readable_code`: Can be `true` or `false`, indicates if the human readable contents should be printed below the barcode.
128
+
129
+ The available barcode types are:
130
+
131
+ * `Zebra::Zpl::BarcodeType::CODE_39`
132
+ * `Zebra::Zpl::BarcodeType::CODE_93`
133
+ * `Zebra::Zpl::BarcodeType::CODE_128_AUTO`
134
+ * `Zebra::Zpl::BarcodeType::CODABAR`
135
+ * `Zebra::Zpl::BarcodeType::CODE_AZTEC`
136
+ * `Zebra::Zpl::BarcodeType::CODE_AZTEC_PARAMS`
137
+ * `Zebra::Zpl::BarcodeType::CODE_UPS_MAXICODE`
138
+ * `Zebra::Zpl::BarcodeType::CODE_QR`
139
+
140
+ #### QR Codes
141
+
142
+ You can create QR Codes elements to print using instances of the `Zebra::Zpl::Qrcode` class. It accepts the following options:
143
+
144
+ * `position`: An array with the coordinates to place the QR code, in dots.
145
+ * `scale factor`: Crucial variable of the QR codes's size. Accepted values: 1-99.
146
+ * `error correction level`: Algorithm enables reading damaged QR codes. There are four error correction levels: L - 7% of codewords can be restored, M - 15% can be restored, Q - 25% can be restored, H - 30% can be restored.
147
+
148
+ #### Boxes
149
+
150
+ You can draw boxes in your labels:
151
+
152
+ box = Zebra::Zpl::Box.new :position => [20, 20], :end_position => [100, 100], :line_thickness => 39
153
+
154
+ #### Elements Rotation
155
+
156
+ All printable elements can be rotated on the label, using the `:Rotation` option. The accepted rotation values are:
157
+
158
+ * `Zebra::Zpl::Rotation::NO_ROTATION`: will not rotate the element.
159
+ * `Zebra::Zpl::Rotation::DEGREES_90`: will rotate the element 90 degrees.
160
+ * `Zebra::Zpl::Rotation::DEGREES_180`: will rotate the element 180 degrees.
161
+ * `Zebra::Zpl::Rotation::DEGREES_270`: will rotate the element 270 degrees.
162
+
163
+ #### Elements Justification
164
+
165
+ There are four ZPL-supported `:Justification` parameters. "LEFT" (left-justified) is the default.
166
+
167
+ * `Zebra::Zpl::Justification::LEFT` ~ left-justified
168
+ * `Zebra::Zpl::Justification::RIGHT` ~ right-justified
169
+ * `Zebra::Zpl::Justification::CENTER` ~ centered
170
+ * `Zebra::Zpl::Justification::JUSTIFIED` ~ full-width-justifed _(YMMV)_
171
+
172
+
173
+
174
+ ## Contributing
175
+
176
+ 1. Fork it
177
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
178
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
179
+ 4. Push to the branch (`git push origin my-new-feature`)
180
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,35 @@
1
+ module Zebra
2
+ class PrintJob
3
+ # class UnknownPrinter < StandardError
4
+ # def initialize(printer)
5
+ # super("Could not find a printer named #{printer}")
6
+ # end
7
+ # end
8
+
9
+ attr_reader :printer
10
+
11
+ def initialize(printer)
12
+ #check_existent_printers printer
13
+
14
+ @printer = printer
15
+ end
16
+
17
+ def print(label, ip)
18
+ @remote_ip = ip
19
+ tempfile = label.persist
20
+ send_to_printer tempfile.path
21
+ end
22
+
23
+ private
24
+
25
+ # def check_existent_printers(printer)
26
+ # existent_printers = Cups.show_destinations
27
+ # raise UnknownPrinter.new(printer) unless existent_printers.include?(printer)
28
+ # end
29
+
30
+ def send_to_printer(path)
31
+ puts "* * * * * * * * * * * * Sending file to printer #{@printer} at #{@remote_ip} * * * * * * * * * * "
32
+ `lp -h #{@remote_ip} -d #{@printer} -o raw #{path}`
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,55 @@
1
+ require "zebra/zpl/printable"
2
+
3
+ module Zebra
4
+ module Zpl
5
+ class Barcode
6
+ include Printable
7
+
8
+ class InvalidNarrowBarWidthError < StandardError; end
9
+ class InvalidWideBarWidthError < StandardError; end
10
+
11
+ attr_accessor :height
12
+ attr_reader :type, :narrow_bar_width, :wide_bar_width, :width
13
+ attr_writer :print_human_readable_code
14
+
15
+ def width=(width)
16
+ @width = width || 0
17
+ end
18
+
19
+ def type=(type)
20
+ BarcodeType.validate_barcode_type(type)
21
+ @type = type
22
+ end
23
+
24
+ def narrow_bar_width=(width)
25
+ raise InvalidNarrowBarWidthError unless (1..10).include?(width.to_i)
26
+ @narrow_bar_width = width
27
+ end
28
+
29
+ def wide_bar_width=(width)
30
+ raise InvalidWideBarWidthError unless (2..30).include?(width.to_i)
31
+ @wide_bar_width = width
32
+ end
33
+
34
+ def print_human_readable_code
35
+ @print_human_readable_code || false
36
+ end
37
+
38
+ def to_zpl
39
+ check_attributes
40
+ human_readable = print_human_readable_code ? "Y" : "N"
41
+ "^FW#{rotation}^FO#{x},#{y}^BY#{narrow_bar_width}^B#{type}#{rotation},#{height},#{human_readable}^FD#{data}^FS"
42
+ end
43
+
44
+ private
45
+
46
+ def check_attributes
47
+ super
48
+ raise MissingAttributeError.new("the barcode type to be used is not given") unless @type
49
+ raise MissingAttributeError.new("the height to be used is not given") unless @height
50
+ raise MissingAttributeError.new("the narrow bar width to be used is not given") unless @narrow_bar_width
51
+ raise MissingAttributeError.new("the wide bar width to be used is not given") unless @wide_bar_width
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,34 @@
1
+ module Zebra
2
+ module Zpl
3
+ module BarcodeType
4
+ class InvalidBarcodeTypeError < StandardError; end
5
+
6
+ CODE_39 = "3"
7
+ CODE_93 = "A"
8
+ CODE_128_AUTO = "C"
9
+ CODABAR = "K"
10
+ CODE_AZTEC = "0"
11
+ CODE_AZTEC_PARAMS = "O"
12
+ CODE_UPS_MAXICODE = "D"
13
+ CODE_QR = "Q"
14
+
15
+ # Legacy (EPL) bar code suffixes
16
+ # CODE_39 = "3"
17
+ # CODE_39_CHECK_DIGIT = "3C"
18
+ # CODE_93 = "9"
19
+ # CODE_128_AUTO = "1"
20
+ # CODE_128_A = "1A"
21
+ # CODE_128_B = "1B"
22
+ # CODE_128_C = "1C"
23
+ # CODABAR = "K"
24
+
25
+ def self.valid_barcode_type?(type)
26
+ %w(3 A C K 0 O D Q).include? type
27
+ end
28
+
29
+ def self.validate_barcode_type(type)
30
+ raise InvalidBarcodeTypeError unless valid_barcode_type?(type)
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,50 @@
1
+ require "zebra/zpl/printable"
2
+
3
+ module Zebra
4
+ module Zpl
5
+ class Box
6
+ include Printable
7
+
8
+ class InvalidLineThickness < StandardError; end
9
+
10
+ attr_reader :line_thickness, :box_width, :box_height, :width
11
+
12
+ def line_thickness=(thickness)
13
+ raise InvalidLineThickness unless thickness.nil? || thickness.to_i.to_s == thickness.to_s
14
+ @line_thickness = thickness
15
+ end
16
+
17
+ def box_width=(width)
18
+ @box_width = width
19
+ end
20
+
21
+ ### The method below refers to the "label width"
22
+ def width=(width)
23
+ @width = width || 0
24
+ end
25
+
26
+ def box_height=(height)
27
+ @box_height = height
28
+ end
29
+
30
+ def to_zpl
31
+ check_attributes
32
+ # "^FO#{x},#{y}^GB#{box_width},#{box_height},#{line_thickness}^FS"
33
+ "^FO#{x},#{y}^GB#{box_width},#{box_height},#{line_thickness}^FS"
34
+ end
35
+
36
+ private
37
+
38
+ def has_data?
39
+ false
40
+ end
41
+
42
+ def check_attributes
43
+ super
44
+ raise MissingAttributeError.new("the line thickness is not given") unless line_thickness
45
+ raise MissingAttributeError.new("the box_width is not given") unless box_width
46
+ raise MissingAttributeError.new("the box_height is not given") unless box_height
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,45 @@
1
+ # encoding: utf-8
2
+ module Zebra
3
+ module Zpl
4
+ class CharacterSet
5
+ class InvalidNumberOfDataBits < StandardError; end
6
+ class CountryCodeNotApplicableForNumberOfDataBits < StandardError; end
7
+ class MissingAttributeError < StandardError
8
+ def initialize(attr)
9
+ super("Can't set character set if the #{attr} is not given")
10
+ end
11
+ end
12
+
13
+ attr_reader :number_of_data_bits, :language, :country_code
14
+
15
+ def initialize(options = {})
16
+ options.each_pair { |attribute, value| self.__send__ "#{attribute}=", value }
17
+ end
18
+
19
+ def number_of_data_bits=(nodb)
20
+ raise InvalidNumberOfDataBits unless [7, 8, nil].include?(nodb)
21
+ @number_of_data_bits = nodb
22
+ end
23
+
24
+ def language=(l)
25
+ Language.validate_language(l) unless l.nil?
26
+ @language = l
27
+ end
28
+
29
+ def country_code=(code)
30
+ CountryCode.validate_country_code(code) unless code.nil?
31
+ @country_code = code
32
+ end
33
+
34
+ def to_zpl
35
+ raise MissingAttributeError.new("language") if language.nil?
36
+ raise MissingAttributeError.new("number of data bits") if number_of_data_bits.nil?
37
+ raise MissingAttributeError.new("country code") if number_of_data_bits == 8 && country_code.nil?
38
+ raise CountryCodeNotApplicableForNumberOfDataBits if number_of_data_bits == 7 && !country_code.nil?
39
+ Language.validate_language_for_number_of_data_bits language, number_of_data_bits
40
+
41
+ ["I#{number_of_data_bits}", language, country_code].compact.join(",")
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,36 @@
1
+ # encoding: utf-8
2
+ module Zebra
3
+ module Zpl
4
+ class CountryCode
5
+ class InvalidCountryCodeError < StandardError; end
6
+
7
+ BELGIUM = "032"
8
+ CANADA = "002"
9
+ DENMARK = "045"
10
+ FINLAND = "358"
11
+ FRANCE = "033"
12
+ GERMANY = "049"
13
+ NETHERLANDS = "031"
14
+ ITALY = "039"
15
+ LATIN_AMERICA = "003"
16
+ NORWAY = "047"
17
+ PORTUGAL = "351"
18
+ SOUTH_AFRICA = "027"
19
+ SPAIN = "034"
20
+ SWEDEN = "046"
21
+ SWITZERLAND = "041"
22
+ UK = "044"
23
+ USA = "001"
24
+
25
+ def self.valid_country_code?(code)
26
+ [BELGIUM, CANADA, DENMARK, FINLAND, FRANCE, GERMANY, NETHERLANDS,
27
+ ITALY, LATIN_AMERICA, NORWAY, PORTUGAL, SOUTH_AFRICA, SPAIN, SWEDEN, SWITZERLAND,
28
+ UK, USA].include?(code)
29
+ end
30
+
31
+ def self.validate_country_code(code)
32
+ raise InvalidCountryCodeError unless valid_country_code?(code)
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,47 @@
1
+ module Zebra
2
+ module Zpl
3
+ module FontSize
4
+ class InvalidFontSizeError < StandardError; end
5
+
6
+ SIZE_0 = 12 # tiny
7
+ SIZE_1 = 17 # 6pt
8
+ SIZE_2 = 22 # 8pt
9
+ SIZE_3 = 28 # 10pt
10
+ SIZE_4 = 33 # 12pt
11
+ SIZE_5 = 44 # 16pt
12
+ SIZE_6 = 67 # 24pt
13
+ SIZE_7 = 100 # 32pt
14
+ SIZE_8 = 111 # 40pt
15
+ SIZE_9 = 133 # 48pt
16
+
17
+ def self.valid_font_size?(font_size)
18
+ [12, 17, 22, 28, 33, 44, 67, 100, 111, 133].include?(font_size.to_i)
19
+ end
20
+
21
+ def self.validate_font_size(font_size)
22
+ raise InvalidFontSizeError unless valid_font_size?(font_size)
23
+ end
24
+ end
25
+
26
+ module FontType
27
+ class InvalidFontTypeError < StandardError; end
28
+
29
+ TYPE_0 = "0" # 6pt
30
+ TYPE_CD = "CD" # 6pt
31
+ TYPE_A = "A" # 6pt
32
+ TYPE_B = "B" # 6pt
33
+ TYPE_E = "E" # 6pt
34
+ TYPE_F = "F" # 6pt
35
+ TYPE_G = "G" # 6pt
36
+ TYPE_H = "H" # 6pt
37
+
38
+ def self.valid_font_type?(font_type)
39
+ ["0", "CD", "A", "B", "E", "F", "G", "H"].include?(font_type)
40
+ end
41
+
42
+ def self.validate_font_type(font_type)
43
+ raise InvalidFontTypeError unless valid_font_type?(font_type)
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,21 @@
1
+ module Zebra
2
+ module Zpl
3
+ module Justification
4
+ class InvalidJustificationError < StandardError; end
5
+
6
+ # ZPL-supported values ("L" is default)
7
+ LEFT = 'L'
8
+ RIGHT = 'R'
9
+ CENTER = 'C'
10
+ JUSTIFIED = 'J'
11
+
12
+ def self.valid_justification?(justification)
13
+ [LEFT, RIGHT, CENTER, JUSTIFIED].include? justification
14
+ end
15
+
16
+ def self.validate_justification(justification)
17
+ raise InvalidJustificationError unless valid_justification?(justification)
18
+ end
19
+ end
20
+ end
21
+ end