qrcode 0.0.1 → 0.1.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 +7 -0
- checksums.yaml.gz.sig +0 -0
- data/.github/copilot-instructions.md +20 -0
- data/.github/workflows/documentation-coverage.yaml +24 -0
- data/.github/workflows/documentation.yaml +57 -0
- data/.github/workflows/rubocop.yaml +21 -0
- data/.github/workflows/test-coverage.yaml +58 -0
- data/.github/workflows/test-external.yaml +33 -0
- data/.github/workflows/test.yaml +47 -0
- data/fixtures/qrcode/sample_data.rb +31 -0
- data/lib/qrcode/encoder/bit_buffer.rb +90 -0
- data/lib/qrcode/encoder/code.rb +436 -0
- data/lib/qrcode/encoder/constants.rb +75 -0
- data/lib/qrcode/encoder/error_correction_block.rb +318 -0
- data/lib/qrcode/encoder/math.rb +50 -0
- data/lib/qrcode/encoder/polynomial.rb +69 -0
- data/lib/qrcode/encoder/segment.rb +190 -0
- data/lib/qrcode/encoder/util.rb +269 -0
- data/lib/qrcode/encoder.rb +13 -0
- data/lib/qrcode/output/svg.rb +46 -0
- data/lib/qrcode/output/text.rb +62 -0
- data/lib/qrcode/version.rb +13 -2
- data/lib/qrcode.rb +23 -3
- data/license.md +54 -0
- data/readme.md +58 -0
- data/releases.md +14 -0
- data.tar.gz.sig +0 -0
- metadata +101 -63
- metadata.gz.sig +0 -0
- data/.gitignore +0 -17
- data/Gemfile +0 -4
- data/LICENSE.txt +0 -22
- data/README.md +0 -29
- data/Rakefile +0 -1
- data/qrcode.gemspec +0 -35
@@ -0,0 +1,269 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Released under the MIT License.
|
4
|
+
# Copyright, 2008-2025, by Duncan Robertson.
|
5
|
+
# Copyright, 2009, by Chris Mowforth.
|
6
|
+
# Copyright, 2011, by Gioele Barabucci.
|
7
|
+
# Copyright, 2012-2015, by Björn Blomqvist.
|
8
|
+
# Copyright, 2012, by xn.
|
9
|
+
# Copyright, 2014, by Sean Doig.
|
10
|
+
# Copyright, 2020, by Nathaniel Roman.
|
11
|
+
# Copyright, 2021, by Sam Sayer.
|
12
|
+
# Copyright, 2025, by Samuel Williams.
|
13
|
+
|
14
|
+
require_relative "constants"
|
15
|
+
require_relative "math"
|
16
|
+
require_relative "polynomial"
|
17
|
+
|
18
|
+
module QRCode
|
19
|
+
module Encoder
|
20
|
+
class Util
|
21
|
+
PATTERN_POSITION_TABLE = [
|
22
|
+
[],
|
23
|
+
[6, 18],
|
24
|
+
[6, 22],
|
25
|
+
[6, 26],
|
26
|
+
[6, 30],
|
27
|
+
[6, 34],
|
28
|
+
[6, 22, 38],
|
29
|
+
[6, 24, 42],
|
30
|
+
[6, 26, 46],
|
31
|
+
[6, 28, 50],
|
32
|
+
[6, 30, 54],
|
33
|
+
[6, 32, 58],
|
34
|
+
[6, 34, 62],
|
35
|
+
[6, 26, 46, 66],
|
36
|
+
[6, 26, 48, 70],
|
37
|
+
[6, 26, 50, 74],
|
38
|
+
[6, 30, 54, 78],
|
39
|
+
[6, 30, 56, 82],
|
40
|
+
[6, 30, 58, 86],
|
41
|
+
[6, 34, 62, 90],
|
42
|
+
[6, 28, 50, 72, 94],
|
43
|
+
[6, 26, 50, 74, 98],
|
44
|
+
[6, 30, 54, 78, 102],
|
45
|
+
[6, 28, 54, 80, 106],
|
46
|
+
[6, 32, 58, 84, 110],
|
47
|
+
[6, 30, 58, 86, 114],
|
48
|
+
[6, 34, 62, 90, 118],
|
49
|
+
[6, 26, 50, 74, 98, 122],
|
50
|
+
[6, 30, 54, 78, 102, 126],
|
51
|
+
[6, 26, 52, 78, 104, 130],
|
52
|
+
[6, 30, 56, 82, 108, 134],
|
53
|
+
[6, 34, 60, 86, 112, 138],
|
54
|
+
[6, 30, 58, 86, 114, 142],
|
55
|
+
[6, 34, 62, 90, 118, 146],
|
56
|
+
[6, 30, 54, 78, 102, 126, 150],
|
57
|
+
[6, 24, 50, 76, 102, 128, 154],
|
58
|
+
[6, 28, 54, 80, 106, 132, 158],
|
59
|
+
[6, 32, 58, 84, 110, 136, 162],
|
60
|
+
[6, 26, 54, 82, 110, 138, 166],
|
61
|
+
[6, 30, 58, 86, 114, 142, 170]
|
62
|
+
].freeze
|
63
|
+
|
64
|
+
G15 = 1 << 10 | 1 << 8 | 1 << 5 | 1 << 4 | 1 << 2 | 1 << 1 | 1 << 0
|
65
|
+
G18 = 1 << 12 | 1 << 11 | 1 << 10 | 1 << 9 | 1 << 8 | 1 << 5 | 1 << 2 | 1 << 0
|
66
|
+
G15_MASK = 1 << 14 | 1 << 12 | 1 << 10 | 1 << 4 | 1 << 1
|
67
|
+
|
68
|
+
DEMERIT_POINTS_1 = 3
|
69
|
+
DEMERIT_POINTS_2 = 3
|
70
|
+
DEMERIT_POINTS_3 = 40
|
71
|
+
DEMERIT_POINTS_4 = 10
|
72
|
+
|
73
|
+
BITS_FOR_MODE = {
|
74
|
+
MODE[:mode_number] => [10, 12, 14],
|
75
|
+
MODE[:mode_alpha_numk] => [9, 11, 13],
|
76
|
+
MODE[:mode_8bit_byte] => [8, 16, 16]
|
77
|
+
}.freeze
|
78
|
+
|
79
|
+
# This value is used during the right shift zero fill step. It is
|
80
|
+
# auto set to 32 or 64 depending on the arch of your system running.
|
81
|
+
# 64 consumes a LOT more memory. In tests it's shown changing it to 32
|
82
|
+
# on 64 bit systems greatly reduces the memory footprint. You can use
|
83
|
+
# RQRCODE_CORE_ARCH_BITS to make this change but beware it may also
|
84
|
+
# have unintended consequences so use at your own risk.
|
85
|
+
ARCH_BITS = ENV.fetch("RQRCODE_CORE_ARCH_BITS", nil)&.to_i || 1.size * 8
|
86
|
+
|
87
|
+
def self.max_size
|
88
|
+
PATTERN_POSITION_TABLE.count
|
89
|
+
end
|
90
|
+
|
91
|
+
def self.get_bch_format_info(data)
|
92
|
+
d = data << 10
|
93
|
+
while Encoder::Util.get_bch_digit(d) - Encoder::Util.get_bch_digit(G15) >= 0
|
94
|
+
d ^= (G15 << (Encoder::Util.get_bch_digit(d) - Encoder::Util.get_bch_digit(G15)))
|
95
|
+
end
|
96
|
+
((data << 10) | d) ^ G15_MASK
|
97
|
+
end
|
98
|
+
|
99
|
+
def self.rszf(num, count)
|
100
|
+
# right shift zero fill
|
101
|
+
(num >> count) & ((1 << (ARCH_BITS - count)) - 1)
|
102
|
+
end
|
103
|
+
|
104
|
+
def self.get_bch_version(data)
|
105
|
+
d = data << 12
|
106
|
+
while Encoder::Util.get_bch_digit(d) - Encoder::Util.get_bch_digit(G18) >= 0
|
107
|
+
d ^= (G18 << (Encoder::Util.get_bch_digit(d) - Encoder::Util.get_bch_digit(G18)))
|
108
|
+
end
|
109
|
+
(data << 12) | d
|
110
|
+
end
|
111
|
+
|
112
|
+
def self.get_bch_digit(data)
|
113
|
+
digit = 0
|
114
|
+
|
115
|
+
while data != 0
|
116
|
+
digit += 1
|
117
|
+
data = Encoder::Util.rszf(data, 1)
|
118
|
+
end
|
119
|
+
|
120
|
+
digit
|
121
|
+
end
|
122
|
+
|
123
|
+
def self.get_pattern_positions(version)
|
124
|
+
PATTERN_POSITION_TABLE[version - 1]
|
125
|
+
end
|
126
|
+
|
127
|
+
def self.get_mask(mask_pattern, i, j)
|
128
|
+
if mask_pattern > MASK_COMPUTATIONS.size
|
129
|
+
raise RuntimeError, "bad mask_pattern: #{mask_pattern}"
|
130
|
+
end
|
131
|
+
|
132
|
+
MASK_COMPUTATIONS[mask_pattern].call(i, j)
|
133
|
+
end
|
134
|
+
|
135
|
+
def self.get_error_correct_polynomial(error_correct_length)
|
136
|
+
a = Encoder::Polynomial.new([1], 0)
|
137
|
+
|
138
|
+
(0...error_correct_length).each do |i|
|
139
|
+
a = a.multiply(Encoder::Polynomial.new([1, Encoder::Math.gexp(i)], 0))
|
140
|
+
end
|
141
|
+
|
142
|
+
a
|
143
|
+
end
|
144
|
+
|
145
|
+
def self.get_length_in_bits(mode, version)
|
146
|
+
if !MODE.value?(mode)
|
147
|
+
raise RuntimeError, "Unknown mode: #{mode}"
|
148
|
+
end
|
149
|
+
|
150
|
+
if version > 40
|
151
|
+
raise RuntimeError, "Unknown version: #{version}"
|
152
|
+
end
|
153
|
+
|
154
|
+
if version.between?(1, 9)
|
155
|
+
# 1 - 9
|
156
|
+
macro_version = 0
|
157
|
+
elsif version <= 26
|
158
|
+
# 10 - 26
|
159
|
+
macro_version = 1
|
160
|
+
elsif version <= 40
|
161
|
+
# 27 - 40
|
162
|
+
macro_version = 2
|
163
|
+
end
|
164
|
+
|
165
|
+
BITS_FOR_MODE[mode][macro_version]
|
166
|
+
end
|
167
|
+
|
168
|
+
def self.get_lost_points(modules)
|
169
|
+
demerit_points = 0
|
170
|
+
|
171
|
+
demerit_points += Encoder::Util.demerit_points_1_same_color(modules)
|
172
|
+
demerit_points += Encoder::Util.demerit_points_2_full_blocks(modules)
|
173
|
+
demerit_points += Encoder::Util.demerit_points_3_dangerous_patterns(modules)
|
174
|
+
demerit_points += Encoder::Util.demerit_points_4_dark_ratio(modules)
|
175
|
+
|
176
|
+
demerit_points
|
177
|
+
end
|
178
|
+
|
179
|
+
def self.demerit_points_1_same_color(modules)
|
180
|
+
demerit_points = 0
|
181
|
+
module_count = modules.size
|
182
|
+
|
183
|
+
# level1
|
184
|
+
(0...module_count).each do |row|
|
185
|
+
(0...module_count).each do |col|
|
186
|
+
same_count = 0
|
187
|
+
dark = modules[row][col]
|
188
|
+
|
189
|
+
(-1..1).each do |r|
|
190
|
+
next if row + r < 0 || module_count <= row + r
|
191
|
+
|
192
|
+
(-1..1).each do |c|
|
193
|
+
next if col + c < 0 || module_count <= col + c
|
194
|
+
next if r == 0 && c == 0
|
195
|
+
if dark == modules[row + r][col + c]
|
196
|
+
same_count += 1
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
if same_count > 5
|
202
|
+
demerit_points += (DEMERIT_POINTS_1 + same_count - 5)
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
demerit_points
|
208
|
+
end
|
209
|
+
|
210
|
+
def self.demerit_points_2_full_blocks(modules)
|
211
|
+
demerit_points = 0
|
212
|
+
module_count = modules.size
|
213
|
+
|
214
|
+
# level 2
|
215
|
+
(0...(module_count - 1)).each do |row|
|
216
|
+
(0...(module_count - 1)).each do |col|
|
217
|
+
count = 0
|
218
|
+
count += 1 if modules[row][col]
|
219
|
+
count += 1 if modules[row + 1][col]
|
220
|
+
count += 1 if modules[row][col + 1]
|
221
|
+
count += 1 if modules[row + 1][col + 1]
|
222
|
+
if count == 0 || count == 4
|
223
|
+
demerit_points += DEMERIT_POINTS_2
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
demerit_points
|
229
|
+
end
|
230
|
+
|
231
|
+
def self.demerit_points_3_dangerous_patterns(modules)
|
232
|
+
demerit_points = 0
|
233
|
+
module_count = modules.size
|
234
|
+
|
235
|
+
# level 3
|
236
|
+
modules.each do |row|
|
237
|
+
(module_count - 6).times do |col_idx|
|
238
|
+
if row[col_idx] && !row[col_idx + 1] && row[col_idx + 2] && row[col_idx + 3] && row[col_idx + 4] && !row[col_idx + 5] && row[col_idx + 6]
|
239
|
+
demerit_points += DEMERIT_POINTS_3
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
(0...module_count).each do |col|
|
245
|
+
(0...(module_count - 6)).each do |row|
|
246
|
+
if modules[row][col] && !modules[row + 1][col] && modules[row + 2][col] && modules[row + 3][col] && modules[row + 4][col] && !modules[row + 5][col] && modules[row + 6][col]
|
247
|
+
demerit_points += DEMERIT_POINTS_3
|
248
|
+
end
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
demerit_points
|
253
|
+
end
|
254
|
+
|
255
|
+
def self.demerit_points_4_dark_ratio(modules)
|
256
|
+
# level 4
|
257
|
+
dark_count = modules.reduce(0) do |sum, col|
|
258
|
+
sum + col.count(true)
|
259
|
+
end
|
260
|
+
|
261
|
+
# Convert to float to prevent integer division
|
262
|
+
ratio = dark_count.to_f / (modules.size * modules.size)
|
263
|
+
ratio_delta = (100 * ratio - 50).abs / 5
|
264
|
+
|
265
|
+
ratio_delta * DEMERIT_POINTS_4
|
266
|
+
end
|
267
|
+
end
|
268
|
+
end
|
269
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Released under the MIT License.
|
4
|
+
# Copyright, 2025, by Samuel Williams.
|
5
|
+
|
6
|
+
module QRCode
|
7
|
+
module Output
|
8
|
+
# SVG renderer for scalable vector graphics
|
9
|
+
class SVG
|
10
|
+
attr_reader :qrcode, :cell_size, :border, :dark_color, :light_color
|
11
|
+
|
12
|
+
def initialize(qrcode, cell_size: 10, border: 2, dark_color: "#000000", light_color: "#ffffff")
|
13
|
+
@qrcode = qrcode
|
14
|
+
@cell_size = cell_size
|
15
|
+
@border = border
|
16
|
+
@dark_color = dark_color
|
17
|
+
@light_color = light_color
|
18
|
+
end
|
19
|
+
|
20
|
+
def render
|
21
|
+
total_size = (qrcode.size + (border * 2)) * cell_size
|
22
|
+
|
23
|
+
svg = []
|
24
|
+
svg << %[<?xml version="1.0" encoding="UTF-8"?>]
|
25
|
+
svg << %[<svg xmlns="http://www.w3.org/2000/svg" width="#{total_size}" height="#{total_size}" viewBox="0 0 #{total_size} #{total_size}">]
|
26
|
+
|
27
|
+
# Background rectangle
|
28
|
+
svg << %[ <rect x="0" y="0" width="#{total_size}" height="#{total_size}" fill="#{light_color}"/>]
|
29
|
+
|
30
|
+
# Generate dark modules as rectangles
|
31
|
+
qrcode.size.times do |row|
|
32
|
+
qrcode.size.times do |col|
|
33
|
+
if qrcode.checked?(row, col)
|
34
|
+
x = (col + border) * cell_size
|
35
|
+
y = (row + border) * cell_size
|
36
|
+
svg << %[ <rect x="#{x}" y="#{y}" width="#{cell_size}" height="#{cell_size}" fill="#{dark_color}"/>]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
svg << %[</svg>]
|
42
|
+
svg.join("\n")
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Released under the MIT License.
|
4
|
+
# Copyright, 2025, by Samuel Williams.
|
5
|
+
|
6
|
+
module QRCode
|
7
|
+
module Output
|
8
|
+
# Text renderer using Unicode half-height block characters
|
9
|
+
class Text
|
10
|
+
# Unicode block characters for different combinations
|
11
|
+
BLOCKS = {
|
12
|
+
[false, false] => " ", # Both light - single space
|
13
|
+
[false, true] => "▄", # Top light, bottom dark
|
14
|
+
[true, false] => "▀", # Top dark, bottom light
|
15
|
+
[true, true] => "█" # Both dark - full block
|
16
|
+
}.freeze
|
17
|
+
|
18
|
+
attr_reader :qrcode, :border
|
19
|
+
|
20
|
+
def initialize(qrcode, border: 2)
|
21
|
+
@qrcode = qrcode
|
22
|
+
@border = border
|
23
|
+
end
|
24
|
+
|
25
|
+
def render
|
26
|
+
lines = []
|
27
|
+
|
28
|
+
# Add top border
|
29
|
+
border.times do
|
30
|
+
lines << " " * total_width
|
31
|
+
end
|
32
|
+
|
33
|
+
# Process QR code in pairs of rows to use half-height blocks
|
34
|
+
(0...qrcode.size).step(2) do |row|
|
35
|
+
line = " " * border # Left border
|
36
|
+
|
37
|
+
qrcode.size.times do |col|
|
38
|
+
top = qrcode.checked?(row, col)
|
39
|
+
bottom = (row + 1 < qrcode.size) ? qrcode.checked?(row + 1, col) : false
|
40
|
+
line += BLOCKS[[top, bottom]]
|
41
|
+
end
|
42
|
+
|
43
|
+
line += " " * border # Right border
|
44
|
+
lines << line
|
45
|
+
end
|
46
|
+
|
47
|
+
# Add bottom border
|
48
|
+
border.times do
|
49
|
+
lines << " " * total_width
|
50
|
+
end
|
51
|
+
|
52
|
+
lines.join("\n")
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def total_width
|
58
|
+
qrcode.size + (border * 2)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
data/lib/qrcode/version.rb
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Released under the MIT License.
|
4
|
+
# Copyright, 2011-2025, by Duncan Robertson.
|
5
|
+
# Copyright, 2012-2016, by Björn Blomqvist.
|
6
|
+
# Copyright, 2012, by xn.
|
7
|
+
# Copyright, 2013, by Yauhen Kharuzhy.
|
8
|
+
# Copyright, 2015, by Tonči Damjanić.
|
9
|
+
# Copyright, 2015, by Bjorn Blomqvist.
|
10
|
+
# Copyright, 2025, by Samuel Williams.
|
11
|
+
|
12
|
+
module QRCode
|
13
|
+
VERSION = "0.1.1"
|
3
14
|
end
|
data/lib/qrcode.rb
CHANGED
@@ -1,5 +1,25 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
# Released under the MIT License.
|
4
|
+
# Copyright, 2019-2020, by Duncan Robertson.
|
5
|
+
# Copyright, 2020, by Nathaniel Roman.
|
6
|
+
# Copyright, 2025, by Samuel Williams.
|
7
|
+
|
8
|
+
require_relative "qrcode/version"
|
9
|
+
require_relative "qrcode/encoder"
|
10
|
+
require_relative "qrcode/output/text"
|
11
|
+
require_relative "qrcode/output/svg"
|
12
|
+
|
13
|
+
module QRCode
|
14
|
+
# Convenience method to create a QR code and render as text
|
15
|
+
def self.text(data, level: :h, mode: :auto, size: nil, max_size: nil, **output_options)
|
16
|
+
qr = Encoder::Code.build(data, level: level, mode: mode, size: size, max_size: max_size)
|
17
|
+
Output::Text.new(qr, **output_options).render
|
18
|
+
end
|
19
|
+
|
20
|
+
# Convenience method to create a QR code and render as SVG
|
21
|
+
def self.svg(data, level: :h, mode: :auto, size: nil, max_size: nil, **output_options)
|
22
|
+
qr = Encoder::Code.build(data, level: level, mode: mode, size: size, max_size: max_size)
|
23
|
+
Output::SVG.new(qr, **output_options).render
|
24
|
+
end
|
5
25
|
end
|
data/license.md
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
# MIT License
|
2
|
+
|
3
|
+
Copyright, 2008-2025, by Duncan Robertson.
|
4
|
+
Copyright, 2009, by Chris Mowforth.
|
5
|
+
Copyright, 2009, by Tore Darell.
|
6
|
+
Copyright, 2011, by Daniel Schierbeck.
|
7
|
+
Copyright, 2011, by Ken Collins.
|
8
|
+
Copyright, 2011, by Gioele Barabucci.
|
9
|
+
Copyright, 2011, by Marcos Piccinini.
|
10
|
+
Copyright, 2012-2018, by Björn Blomqvist.
|
11
|
+
Copyright, 2012, by xn.
|
12
|
+
Copyright, 2013, by Yauhen Kharuzhy.
|
13
|
+
Copyright, 2013, by Andreas Finger.
|
14
|
+
Copyright, 2013-2016, by Bjorn Blomqvist.
|
15
|
+
Copyright, 2013, by Jon Evans.
|
16
|
+
Copyright, 2014, by Sean Doig.
|
17
|
+
Copyright, 2015, by Bart Jedrocha.
|
18
|
+
Copyright, 2015, by Simon Males.
|
19
|
+
Copyright, 2015, by Ferdinand Rosario.
|
20
|
+
Copyright, 2015, by Christopher Lord.
|
21
|
+
Copyright, 2015, by José Luis Honorato.
|
22
|
+
Copyright, 2015, by Tonči Damjanić.
|
23
|
+
Copyright, 2015-2016, by Fabio Napoleoni.
|
24
|
+
Copyright, 2016, by Christian Campbell.
|
25
|
+
Copyright, 2016, by Andy Brody.
|
26
|
+
Copyright, 2017, by Nicolò Gnudi.
|
27
|
+
Copyright, 2019, by Thibaut Barrère.
|
28
|
+
Copyright, 2019, by Masataka Pocke Kuwabara.
|
29
|
+
Copyright, 2020, by Nathaniel Roman.
|
30
|
+
Copyright, 2020, by dependabot[bot].
|
31
|
+
Copyright, 2020, by Jeremy Evans.
|
32
|
+
Copyright, 2021, by Simon Schrape.
|
33
|
+
Copyright, 2021, by Sam Sayer.
|
34
|
+
Copyright, 2022, by James Neal.
|
35
|
+
Copyright, 2025, by Matt Rohrer.
|
36
|
+
Copyright, 2025, by Samuel Williams.
|
37
|
+
|
38
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
39
|
+
of this software and associated documentation files (the "Software"), to deal
|
40
|
+
in the Software without restriction, including without limitation the rights
|
41
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
42
|
+
copies of the Software, and to permit persons to whom the Software is
|
43
|
+
furnished to do so, subject to the following conditions:
|
44
|
+
|
45
|
+
The above copyright notice and this permission notice shall be included in all
|
46
|
+
copies or substantial portions of the Software.
|
47
|
+
|
48
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
49
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
50
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
51
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
52
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
53
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
54
|
+
SOFTWARE.
|
data/readme.md
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
# QRCode
|
2
|
+
|
3
|
+
A pure Ruby library for generating QR codes with multiple output formats. Generate QR codes as text art for terminal display or as scalable SVG graphics for web and print applications.
|
4
|
+
|
5
|
+
This is a fork of [`rqrcode_core`](https://github.com/whomwah/rqrcode_core), which was originally adapted in 2008 from a Javascript library by [Kazuhiko Arase](https://github.com/kazuhikoarase/qrcode-generator).
|
6
|
+
|
7
|
+
[](https://github.com/socketry/qrcode/actions?workflow=Test)
|
8
|
+
|
9
|
+
## Features
|
10
|
+
|
11
|
+
- **Pure Ruby**: No external dependencies, works with any Ruby application.
|
12
|
+
- **Multiple Output Formats**: Text (Unicode blocks) and SVG output built-in.
|
13
|
+
- **Automatic Optimization**: Intelligently selects the most efficient encoding (numeric, alphanumeric, or binary).
|
14
|
+
- **Error Correction**: Full support for all four standardized error correction levels (L, M, Q, H).
|
15
|
+
- **Multi-Segment Encoding**: Optimize large data by mixing encoding modes in a single QR code.
|
16
|
+
- **Command Line Tools**: Bake tasks for generating QR codes from the terminal.
|
17
|
+
- **Standards Compliant**: Follows ISO/IEC 18004 QR Code specification.
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
Please see the [project documentation](https://socketry.github.io/qrcode/) for more details.
|
22
|
+
|
23
|
+
- [Getting Started](https://socketry.github.io/qrcode/guides/getting-started/index) - This guide explains how to get started with `qrcode` to generate QR codes in Ruby.
|
24
|
+
|
25
|
+
## Releases
|
26
|
+
|
27
|
+
Please see the [project releases](https://socketry.github.io/qrcode/releases/index) for all releases.
|
28
|
+
|
29
|
+
### v0.1.0
|
30
|
+
|
31
|
+
- **Breaking**: Complete refactor of encoder architecture with cleaner segment-based design.
|
32
|
+
- **Breaking**: Renamed `RSBlock` to `ErrorCorrectionBlock` with cleaner method names (`for`, `table_entry_for`).
|
33
|
+
- **Breaking**: Simplified `Code` constructor to take segments array, added `Code.build()` factory method.
|
34
|
+
- **Breaking**: Removed redundant `Multi` class - multi-segment support now built into `Code` directly.
|
35
|
+
- Added self-contained segment classes: `Segment`, `NumericSegment`, `AlphanumericSegment`.
|
36
|
+
- Added comprehensive test coverage for output functionality (Text and SVG).
|
37
|
+
- Added `size` alias for `module_count` for cleaner API.
|
38
|
+
- Added proper documentation explaining error correction level encoding from ISO/IEC 18004.
|
39
|
+
- Improved code organization with `QRCode::Encoder` namespace for all encoding classes.
|
40
|
+
- Removed QR prefix from encoder file and class names for cleaner codebase.
|
41
|
+
|
42
|
+
## Contributing
|
43
|
+
|
44
|
+
We welcome contributions to this project.
|
45
|
+
|
46
|
+
1. Fork it.
|
47
|
+
2. Create your feature branch (`git checkout -b my-new-feature`).
|
48
|
+
3. Commit your changes (`git commit -am 'Add some feature'`).
|
49
|
+
4. Push to the branch (`git push origin my-new-feature`).
|
50
|
+
5. Create new Pull Request.
|
51
|
+
|
52
|
+
### Developer Certificate of Origin
|
53
|
+
|
54
|
+
In order to protect users of this project, we require all contributors to comply with the [Developer Certificate of Origin](https://developercertificate.org/). This ensures that all contributions are properly licensed and attributed.
|
55
|
+
|
56
|
+
### Community Guidelines
|
57
|
+
|
58
|
+
This project is best served by a collaborative and respectful environment. Treat each other professionally, respect differing viewpoints, and engage constructively. Harassment, discrimination, or harmful behavior is not tolerated. Communicate clearly, listen actively, and support one another. If any issues arise, please inform the project maintainers.
|
data/releases.md
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# Releases
|
2
|
+
|
3
|
+
## v0.1.0
|
4
|
+
|
5
|
+
- **Breaking**: Complete refactor of encoder architecture with cleaner segment-based design.
|
6
|
+
- **Breaking**: Renamed `RSBlock` to `ErrorCorrectionBlock` with cleaner method names (`for`, `table_entry_for`).
|
7
|
+
- **Breaking**: Simplified `Code` constructor to take segments array, added `Code.build()` factory method.
|
8
|
+
- **Breaking**: Removed redundant `Multi` class - multi-segment support now built into `Code` directly.
|
9
|
+
- Added self-contained segment classes: `Segment`, `NumericSegment`, `AlphanumericSegment`.
|
10
|
+
- Added comprehensive test coverage for output functionality (Text and SVG).
|
11
|
+
- Added `size` alias for `module_count` for cleaner API.
|
12
|
+
- Added proper documentation explaining error correction level encoding from ISO/IEC 18004.
|
13
|
+
- Improved code organization with `QRCode::Encoder` namespace for all encoding classes.
|
14
|
+
- Removed QR prefix from encoder file and class names for cleaner codebase.
|
data.tar.gz.sig
ADDED
Binary file
|