rqrcode_core 0.1.2 → 1.2.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.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +12 -14
- data/.gitignore +1 -0
- data/CHANGELOG.md +44 -0
- data/Gemfile.lock +33 -4
- data/README.md +56 -21
- data/Rakefile +17 -8
- data/lib/rqrcode_core/qrcode/qr_8bit_byte.rb +4 -12
- data/lib/rqrcode_core/qrcode/qr_alphanumeric.rb +18 -25
- data/lib/rqrcode_core/qrcode/qr_bit_buffer.rb +14 -24
- data/lib/rqrcode_core/qrcode/qr_code.rb +210 -286
- data/lib/rqrcode_core/qrcode/qr_math.rb +9 -10
- data/lib/rqrcode_core/qrcode/qr_multi.rb +13 -0
- data/lib/rqrcode_core/qrcode/qr_numeric.rb +9 -20
- data/lib/rqrcode_core/qrcode/qr_polynomial.rb +15 -15
- data/lib/rqrcode_core/qrcode/qr_rs_block.rb +8 -10
- data/lib/rqrcode_core/qrcode/qr_segment.rb +61 -0
- data/lib/rqrcode_core/qrcode/qr_util.rb +48 -49
- data/lib/rqrcode_core/qrcode.rb +11 -9
- data/lib/rqrcode_core/version.rb +1 -1
- data/rqrcode_core.gemspec +17 -17
- metadata +21 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ea3856aba6c1bc5602b3f7fa4126187fe26c47fdba56447b709871f96f432ff5
|
4
|
+
data.tar.gz: eab7166c0e00478bcdb12ab6a550a9a9b595401bf5f6c0271c6bac95b722564f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b9d1977c291eaed204644f09d3900b2ea18bde93e1c242628bdf1c4cd30573c046328e3cdbfe294c6ae27370f5963cdfa8454f1f2e6af7bf185e32cd0fefe592
|
7
|
+
data.tar.gz: 56d9c31b3c056a47ffccc2848f43e0e44d3b3a984f0ef4c332505fae31dadda0ca6adac5ad0566443dbf46a86a2b81b419806cf71a9da6880d51eacd583cbb34
|
data/.github/workflows/ruby.yml
CHANGED
@@ -10,22 +10,20 @@ on:
|
|
10
10
|
- master
|
11
11
|
|
12
12
|
jobs:
|
13
|
-
|
14
|
-
name: Test Ruby ${{ matrix.ruby_version }} on ${{ matrix.os }}
|
15
|
-
runs-on: ${{ matrix.os }}
|
13
|
+
Build:
|
16
14
|
strategy:
|
15
|
+
fail-fast: false
|
17
16
|
matrix:
|
18
|
-
|
19
|
-
|
20
|
-
|
17
|
+
os: [ubuntu-latest, macos-latest]
|
18
|
+
ruby: [2.5, 2.6, 2.7, 3.0]
|
19
|
+
runs-on: ${{ matrix.os }}
|
21
20
|
steps:
|
22
21
|
- uses: actions/checkout@v1
|
23
|
-
-
|
24
|
-
uses: actions/setup-ruby@v1
|
22
|
+
- uses: ruby/setup-ruby@v1
|
25
23
|
with:
|
26
|
-
ruby-version: ${{ matrix.
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
24
|
+
ruby-version: ${{ matrix.ruby }}
|
25
|
+
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
|
26
|
+
- name: Run Tests
|
27
|
+
run: bundle exec rake test
|
28
|
+
- name: StandardRB Check
|
29
|
+
run: bundle exec standardrb --format progress
|
data/.gitignore
CHANGED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
All notable changes to this project will be documented in this file.
|
4
|
+
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
7
|
+
|
8
|
+
## [Unreleased]
|
9
|
+
|
10
|
+
## [1.2.0] - 2021-08-26
|
11
|
+
|
12
|
+
- Added Multi Mode Support which allows for multi-segment encoding. Thanks to [@ssayer](https://github.com/ssayer)
|
13
|
+
|
14
|
+
## [1.1.0] - 2021-07-01
|
15
|
+
|
16
|
+
- Add a basic benchmark file
|
17
|
+
- Add standardRB badge
|
18
|
+
- Add `.freeze` on `CONST` lookup objects
|
19
|
+
- Remove unused `@mode` instance variable
|
20
|
+
- A batch of small refactors and optimizations
|
21
|
+
|
22
|
+
## [1.0.0] - 2021-04-23
|
23
|
+
|
24
|
+
### Changed
|
25
|
+
|
26
|
+
- README updated
|
27
|
+
- Small documentation clarification [@smnscp](https://github.com/smnscp).
|
28
|
+
- Rakefile cleaned up. You can now just run `rake` which will run specs and fix linting using `standardrb`
|
29
|
+
|
30
|
+
### Breaking Changes
|
31
|
+
|
32
|
+
- Very niche but a breaking change never the less. The `to_s` method *no longer* accepts the `:true` and `:false` arguments, but prefers `:dark` and `:light`.
|
33
|
+
|
34
|
+
## [0.2.0] - 2020-12-26
|
35
|
+
|
36
|
+
### Changed
|
37
|
+
|
38
|
+
- fix `required_ruby_version` for Ruby 3 support
|
39
|
+
|
40
|
+
[unreleased]: https://github.com/whomwah/rqrcode_core/compare/v1.2.0...HEAD
|
41
|
+
[1.2.0]: https://github.com/whomwah/rqrcode_core/compare/v1.1.0...v1.2.0
|
42
|
+
[1.1.0]: https://github.com/whomwah/rqrcode_core/compare/v1.0.0...v1.1.0
|
43
|
+
[1.0.0]: https://github.com/whomwah/rqrcode_core/compare/v0.2.0...v1.0.0
|
44
|
+
[0.2.0]: https://github.com/whomwah/rqrcode_core/compare/v0.1.2...v0.2.0
|
data/Gemfile.lock
CHANGED
@@ -1,13 +1,41 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
rqrcode_core (
|
4
|
+
rqrcode_core (1.2.0)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
8
8
|
specs:
|
9
|
-
|
10
|
-
|
9
|
+
ast (2.4.2)
|
10
|
+
minitest (5.14.4)
|
11
|
+
parallel (1.20.1)
|
12
|
+
parser (3.0.2.0)
|
13
|
+
ast (~> 2.4.1)
|
14
|
+
rainbow (3.0.0)
|
15
|
+
rake (13.0.6)
|
16
|
+
regexp_parser (2.1.1)
|
17
|
+
rexml (3.2.5)
|
18
|
+
rubocop (1.18.4)
|
19
|
+
parallel (~> 1.10)
|
20
|
+
parser (>= 3.0.0.0)
|
21
|
+
rainbow (>= 2.2.2, < 4.0)
|
22
|
+
regexp_parser (>= 1.8, < 3.0)
|
23
|
+
rexml
|
24
|
+
rubocop-ast (>= 1.8.0, < 2.0)
|
25
|
+
ruby-progressbar (~> 1.7)
|
26
|
+
unicode-display_width (>= 1.4.0, < 3.0)
|
27
|
+
rubocop-ast (1.9.1)
|
28
|
+
parser (>= 3.0.1.1)
|
29
|
+
rubocop-performance (1.11.4)
|
30
|
+
rubocop (>= 1.7.0, < 2.0)
|
31
|
+
rubocop-ast (>= 0.4.0)
|
32
|
+
ruby-progressbar (1.11.0)
|
33
|
+
standard (1.1.7)
|
34
|
+
rubocop (= 1.18.4)
|
35
|
+
rubocop-performance (= 1.11.4)
|
36
|
+
standardrb (1.0.0)
|
37
|
+
standard
|
38
|
+
unicode-display_width (2.0.0)
|
11
39
|
|
12
40
|
PLATFORMS
|
13
41
|
ruby
|
@@ -17,6 +45,7 @@ DEPENDENCIES
|
|
17
45
|
minitest (~> 5.0)
|
18
46
|
rake (~> 13.0)
|
19
47
|
rqrcode_core!
|
48
|
+
standardrb (~> 1.0)
|
20
49
|
|
21
50
|
BUNDLED WITH
|
22
|
-
2.
|
51
|
+
2.2.22
|
data/README.md
CHANGED
@@ -1,24 +1,25 @@
|
|
1
|
-

|
2
|
+
[](https://github.com/testdouble/standard)
|
2
3
|
|
3
4
|
# RQRCodeCore
|
4
5
|
|
5
|
-
`rqrcode_core` is a library for encoding QR
|
6
|
+
`rqrcode_core` is a library for encoding QR Codes in pure Ruby. It has a simple interface with all the standard qrcode options. It was originally adapted in 2008 from a Javascript library by [Kazuhiko Arase](https://github.com/kazuhikoarase).
|
6
7
|
|
7
8
|
Features:
|
8
9
|
|
9
|
-
* `rqrcode_core` is a
|
10
|
-
* It is an encoding library. You can't decode QR
|
11
|
-
* The interface is simple and assumes you just want to encode a string into a QR
|
12
|
-
* QR
|
10
|
+
* `rqrcode_core` is a Ruby only library. It requires no native libraries. Just Ruby!
|
11
|
+
* It is an encoding library. You can't decode QR Codes with it.
|
12
|
+
* The interface is simple and assumes you just want to encode a string into a QR Code, but also allows for encoding multiple segments.
|
13
|
+
* QR Code is trademarked by Denso Wave inc.
|
13
14
|
|
14
|
-
`rqrcode_core` is the basis of the popular `rqrcode` gem [https://github.com/whomwah/rqrcode]. This gem allows you to generate different renderings of your QR
|
15
|
+
`rqrcode_core` is the basis of the popular `rqrcode` gem [https://github.com/whomwah/rqrcode]. This gem allows you to generate different renderings of your QR Code, including `png`, `svg` and `ansi`.
|
15
16
|
|
16
17
|
## Installation
|
17
18
|
|
18
19
|
Add this line to your application's Gemfile:
|
19
20
|
|
20
21
|
```ruby
|
21
|
-
gem
|
22
|
+
gem "rqrcode_core"
|
22
23
|
```
|
23
24
|
|
24
25
|
And then execute:
|
@@ -32,8 +33,8 @@ Or install it yourself as:
|
|
32
33
|
## Basic Usage
|
33
34
|
|
34
35
|
```ruby
|
35
|
-
$ require
|
36
|
-
$ qr = RQRCodeCore::QRCode.new(
|
36
|
+
$ require "rqrcode_core"
|
37
|
+
$ qr = RQRCodeCore::QRCode.new("https://kyan.com")
|
37
38
|
$ puts qr.to_s
|
38
39
|
```
|
39
40
|
|
@@ -46,15 +47,24 @@ x xxx x xxxxx x xx x xxx x
|
|
46
47
|
... etc
|
47
48
|
```
|
48
49
|
|
50
|
+
## Multiple Encoding Support
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
$ require "rqrcode_core"
|
54
|
+
$ qr = RQRCodeCore::QRCode.new([{data: "byteencoded", mode: :byte_8bit}, {data: "A1" * 100, mode: :alphanumeric}, {data: "1" * 500, mode: :number}])
|
55
|
+
```
|
56
|
+
|
57
|
+
This will create a QR Code with byte encoded, alphanumeric and number segments. Any combination of encodings/segments will work provided it fits within size limits.
|
58
|
+
|
49
59
|
## Doing your own rendering
|
50
60
|
|
51
61
|
```ruby
|
52
|
-
require
|
62
|
+
require "rqrcode_core"
|
53
63
|
|
54
|
-
qr = RQRCodeCore::QRCode.new(
|
55
|
-
qr.
|
64
|
+
qr = RQRCodeCore::QRCode.new("https://kyan.com")
|
65
|
+
qr.rows.each do |row|
|
56
66
|
row.each do |col|
|
57
|
-
print col ?
|
67
|
+
print col ? "#" : " "
|
58
68
|
end
|
59
69
|
|
60
70
|
print "\n"
|
@@ -63,12 +73,14 @@ end
|
|
63
73
|
|
64
74
|
### Options
|
65
75
|
|
66
|
-
The library expects a string to be parsed in, other args are optional.
|
76
|
+
The library expects a string or array (for multiple encodings) to be parsed in, other args are optional.
|
67
77
|
|
68
78
|
```
|
69
|
-
|
79
|
+
data - the string or array you wish to encode
|
80
|
+
|
81
|
+
size - the size (integer) of the QR Code (defaults to smallest size needed to encode the string)
|
70
82
|
|
71
|
-
|
83
|
+
max_size - the max_size (Integer) of the QR Code (default RQRCodeCore::QRUtil.max_size)
|
72
84
|
|
73
85
|
level - the error correction level, can be:
|
74
86
|
* Level :l 7% of code can be restored
|
@@ -76,7 +88,7 @@ level - the error correction level, can be:
|
|
76
88
|
* Level :q 25% of code can be restored
|
77
89
|
* Level :h 30% of code can be restored (default :h)
|
78
90
|
|
79
|
-
mode
|
91
|
+
mode - the mode of the QR Code (defaults to alphanumeric or byte_8bit, depending on the input data, only used when data is a string):
|
80
92
|
* :number
|
81
93
|
* :alphanumeric
|
82
94
|
* :byte_8bit
|
@@ -85,13 +97,36 @@ mode - the mode of the qrcode (defaults to alphanumeric or byte_8bit, dependin
|
|
85
97
|
|
86
98
|
#### Example
|
87
99
|
|
88
|
-
```
|
89
|
-
|
100
|
+
```ruby
|
101
|
+
RQRCodeCore::QRCode.new("http://kyan.com", size: 1, level: :m, mode: :alphanumeric)
|
90
102
|
```
|
91
103
|
|
92
104
|
## Development
|
93
105
|
|
94
|
-
|
106
|
+
### Tests
|
107
|
+
|
108
|
+
You can run the test suite using:
|
109
|
+
|
110
|
+
```
|
111
|
+
$ ./bin/setup
|
112
|
+
$ rake
|
113
|
+
```
|
114
|
+
|
115
|
+
or try the project from the console with:
|
116
|
+
|
117
|
+
```
|
118
|
+
$ ./bin/console
|
119
|
+
```
|
120
|
+
|
121
|
+
### Linting
|
122
|
+
|
123
|
+
The project uses [standardrb](https://github.com/testdouble/standard) and can be run with:
|
124
|
+
|
125
|
+
```
|
126
|
+
$ ./bin/setup
|
127
|
+
$ rake standard # check
|
128
|
+
$ rake standard:fix # fix
|
129
|
+
```
|
95
130
|
|
96
131
|
## Contributing
|
97
132
|
|
data/Rakefile
CHANGED
@@ -1,10 +1,19 @@
|
|
1
|
-
|
2
|
-
require "rake/testtask"
|
1
|
+
begin
|
2
|
+
require "rake/testtask"
|
3
|
+
require "standard/rake"
|
3
4
|
|
4
|
-
Rake::TestTask.new(:test) do |t|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
end
|
5
|
+
Rake::TestTask.new(:test) do |t|
|
6
|
+
t.libs << "test"
|
7
|
+
t.libs << "lib"
|
8
|
+
t.test_files = FileList["test/**/*_test.rb"]
|
9
|
+
end
|
10
|
+
|
11
|
+
task default: [:test, "standard:fix"]
|
9
12
|
|
10
|
-
|
13
|
+
desc "Run a simple benchmark (x1000)"
|
14
|
+
task :benchmark do
|
15
|
+
ruby "test/benchmark.rb"
|
16
|
+
end
|
17
|
+
rescue LoadError
|
18
|
+
# no standard/rspec available
|
19
|
+
end
|
@@ -2,21 +2,13 @@
|
|
2
2
|
|
3
3
|
module RQRCodeCore
|
4
4
|
class QR8bitByte
|
5
|
-
|
6
|
-
|
7
|
-
def initialize( data )
|
8
|
-
@mode = QRMODE[:mode_8bit_byte]
|
9
|
-
@data = data;
|
10
|
-
end
|
11
|
-
|
12
|
-
|
13
|
-
def get_length
|
14
|
-
@data.bytesize
|
5
|
+
def initialize(data)
|
6
|
+
@data = data
|
15
7
|
end
|
16
8
|
|
9
|
+
def write(buffer)
|
10
|
+
buffer.byte_encoding_start(@data.bytesize)
|
17
11
|
|
18
|
-
def write( buffer)
|
19
|
-
buffer.byte_encoding_start(get_length)
|
20
12
|
@data.each_byte do |b|
|
21
13
|
buffer.put(b, 8)
|
22
14
|
end
|
@@ -1,43 +1,36 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module RQRCodeCore
|
4
|
-
ALPHANUMERIC = [
|
4
|
+
ALPHANUMERIC = [
|
5
|
+
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I",
|
6
|
+
"J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", " ", "$",
|
7
|
+
"%", "*", "+", "-", ".", "/", ":"
|
8
|
+
].freeze
|
5
9
|
|
6
10
|
class QRAlphanumeric
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
raise QRCodeArgumentError, "Not a alpha numeric uppercase string `#{data}`" unless QRAlphanumeric.valid_data?(data)
|
13
|
-
|
14
|
-
@data = data;
|
15
|
-
end
|
16
|
-
|
11
|
+
def initialize(data)
|
12
|
+
unless QRAlphanumeric.valid_data?(data)
|
13
|
+
raise QRCodeArgumentError, "Not a alpha numeric uppercase string `#{data}`"
|
14
|
+
end
|
17
15
|
|
18
|
-
|
19
|
-
@data.size
|
16
|
+
@data = data
|
20
17
|
end
|
21
18
|
|
22
|
-
def self.valid_data?
|
23
|
-
data.
|
24
|
-
return false if ALPHANUMERIC.index(s).nil?
|
25
|
-
end
|
26
|
-
true
|
19
|
+
def self.valid_data?(data)
|
20
|
+
(data.chars - ALPHANUMERIC).empty?
|
27
21
|
end
|
28
22
|
|
23
|
+
def write(buffer)
|
24
|
+
buffer.alphanumeric_encoding_start(@data.size)
|
29
25
|
|
30
|
-
|
31
|
-
buffer.alphanumeric_encoding_start(get_length)
|
32
|
-
|
33
|
-
(@data.size).times do |i|
|
26
|
+
@data.size.times do |i|
|
34
27
|
if i % 2 == 0
|
35
28
|
if i == (@data.size - 1)
|
36
29
|
value = ALPHANUMERIC.index(@data[i])
|
37
|
-
buffer.put(
|
30
|
+
buffer.put(value, 6)
|
38
31
|
else
|
39
|
-
value = (ALPHANUMERIC.index(@data[i]) * 45) + ALPHANUMERIC.index(@data[i+1])
|
40
|
-
buffer.put(
|
32
|
+
value = (ALPHANUMERIC.index(@data[i]) * 45) + ALPHANUMERIC.index(@data[i + 1])
|
33
|
+
buffer.put(value, 11)
|
41
34
|
end
|
42
35
|
end
|
43
36
|
end
|
@@ -13,74 +13,64 @@ module RQRCodeCore
|
|
13
13
|
@length = 0
|
14
14
|
end
|
15
15
|
|
16
|
-
|
17
|
-
def get( index )
|
16
|
+
def get(index)
|
18
17
|
buf_index = (index / 8).floor
|
19
|
-
((
|
18
|
+
((QRUtil.rszf(@buffer[buf_index], 7 - index % 8)) & 1) == 1
|
20
19
|
end
|
21
20
|
|
22
|
-
|
23
|
-
|
24
|
-
( 0...length ).each do |i|
|
21
|
+
def put(num, length)
|
22
|
+
(0...length).each do |i|
|
25
23
|
put_bit(((QRUtil.rszf(num, length - i - 1)) & 1) == 1)
|
26
24
|
end
|
27
25
|
end
|
28
26
|
|
29
|
-
|
30
27
|
def get_length_in_bits
|
31
28
|
@length
|
32
29
|
end
|
33
30
|
|
34
|
-
|
35
|
-
|
36
|
-
buf_index = ( @length / 8 ).floor
|
31
|
+
def put_bit(bit)
|
32
|
+
buf_index = (@length / 8).floor
|
37
33
|
if @buffer.size <= buf_index
|
38
34
|
@buffer << 0
|
39
35
|
end
|
40
36
|
|
41
37
|
if bit
|
42
|
-
@buffer[buf_index] |=
|
38
|
+
@buffer[buf_index] |= QRUtil.rszf(0x80, @length % 8)
|
43
39
|
end
|
44
40
|
|
45
41
|
@length += 1
|
46
42
|
end
|
47
43
|
|
48
44
|
def byte_encoding_start(length)
|
49
|
-
|
50
|
-
put( QRMODE[:mode_8bit_byte], 4 )
|
45
|
+
put(QRMODE[:mode_8bit_byte], 4)
|
51
46
|
put(length, QRUtil.get_length_in_bits(QRMODE[:mode_8bit_byte], @version))
|
52
|
-
|
53
47
|
end
|
54
48
|
|
55
49
|
def alphanumeric_encoding_start(length)
|
56
|
-
|
57
|
-
put( QRMODE[:mode_alpha_numk], 4 )
|
50
|
+
put(QRMODE[:mode_alpha_numk], 4)
|
58
51
|
put(length, QRUtil.get_length_in_bits(QRMODE[:mode_alpha_numk], @version))
|
59
|
-
|
60
52
|
end
|
61
53
|
|
62
54
|
def numeric_encoding_start(length)
|
63
|
-
|
64
|
-
put( QRMODE[:mode_number], 4 )
|
55
|
+
put(QRMODE[:mode_number], 4)
|
65
56
|
put(length, QRUtil.get_length_in_bits(QRMODE[:mode_number], @version))
|
66
|
-
|
67
57
|
end
|
68
58
|
|
69
59
|
def pad_until(prefered_size)
|
70
60
|
# Align on byte
|
71
61
|
while get_length_in_bits % 8 != 0
|
72
|
-
put_bit(
|
62
|
+
put_bit(false)
|
73
63
|
end
|
74
64
|
|
75
65
|
# Pad with padding code words
|
76
66
|
while get_length_in_bits < prefered_size
|
77
|
-
put(
|
78
|
-
put(
|
67
|
+
put(PAD0, 8)
|
68
|
+
put(PAD1, 8) if get_length_in_bits < prefered_size
|
79
69
|
end
|
80
70
|
end
|
81
71
|
|
82
72
|
def end_of_message(max_data_bits)
|
83
|
-
put(
|
73
|
+
put(0, 4) unless get_length_in_bits + 4 > max_data_bits
|
84
74
|
end
|
85
75
|
end
|
86
76
|
end
|