rqrcode 1.0.0 → 2.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5aa4c4868eb5c584254a66743407f0461a05be74aece89350d41ea79671bc7d0
4
- data.tar.gz: eb6bbae7b8449b5a3a60ed5faa4d80a99c9bff2ff09b081a38fcac3bed55046c
3
+ metadata.gz: 9dad1e83dc97d564e2ec828cb8ba389c222fa4ae7662d6feaaed36fbfea194ba
4
+ data.tar.gz: e3d901e23ba8dfb7cc6b300ae47bc11dcbc6913d2fce1a66824bffa670ca5cf5
5
5
  SHA512:
6
- metadata.gz: f5c67b502684055b820a1c4d6aa7be65370c493a5431fcb87c9b859486cf9d584806ceffedbeeff50b41c3d524cf8aa02dda535674c33838bbd0943292f26666
7
- data.tar.gz: 1f5295a6b53acea72b83b869666ec004d4bbec494603ee59f7b6ab46401af0bf669c06f9957737c7558e1837c335b3b8da231e28fa18fc167ce6747cc2e1d7d5
6
+ metadata.gz: 317ff35bc49042e5a7a0d9390c82051b9552bd5d2a4c7a56e99e2ea75e7d2d4cf9071516f1fb800e5fd1af3c964976c6354db675c33928a0fee99f54cf588a7c
7
+ data.tar.gz: 167fc518c536b3bf32699dc09952fc5068db81d44040b0b768a4a220186438076992a8a3deb5eb85537c651d1d47ddabe7d4b2a29fbc490027a157b8265e3f77
@@ -1,20 +1,28 @@
1
1
  name: rqrcode
2
2
 
3
- on: [push]
3
+ on:
4
+ push:
5
+ branches:
6
+ - master
7
+ pull_request:
8
+ branches:
9
+ - master
4
10
 
5
11
  jobs:
6
- build:
7
-
8
- runs-on: ubuntu-latest
9
-
12
+ Build:
13
+ strategy:
14
+ fail-fast: false
15
+ matrix:
16
+ os: [ubuntu-latest, macos-latest]
17
+ ruby: [2.5, 2.6, 2.7, 3.0]
18
+ runs-on: ${{ matrix.os }}
10
19
  steps:
11
20
  - uses: actions/checkout@v1
12
- - name: Set up Ruby 2.6
13
- uses: actions/setup-ruby@v1
21
+ - uses: ruby/setup-ruby@v1
14
22
  with:
15
- ruby-version: 2.6.x
16
- - name: Build and test with Rake
17
- run: |
18
- gem install bundler
19
- bundle install --jobs 4 --retry 3
20
- bundle exec rake test
23
+ ruby-version: ${{ matrix.ruby }}
24
+ bundler-cache: true # runs 'bundle install' and caches installed gems automatically
25
+ - name: Run Tests for Ruby ${{ matrix.ruby }} on ${{ matrix.os }}
26
+ run: bundle exec rake spec
27
+ - name: StandardRB check for Ruby ${{ matrix.ruby }} on ${{ matrix.os }}
28
+ run: bundle exec standardrb --format progress
data/.gitignore CHANGED
@@ -10,4 +10,4 @@
10
10
  .rvmrc
11
11
  *.sublime-project
12
12
  *.sublime-workspace
13
- Gemfile.lock
13
+ *.gem
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/CHANGELOG.md ADDED
@@ -0,0 +1,39 @@
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
+ ## [2.0.0] - 2021-05-06
11
+
12
+ ### Added
13
+
14
+ - A new `use_path:` option on `.to_svg`. This uses a `<path>` node to greatly reduce the final SVG size. [#108]
15
+ - A new `viewbox:` option on `.to_svg`. Replaces the `svg.width` and `svg.height` attribute with `svg.viewBox` to allow CSS scaling. [#112]
16
+ - A new `svg_attributes:` option on `.to_svg`. Allows you to pass in custom SVG attributes to be used in the `<svg>` tag. [#113]
17
+
18
+ ### Changed
19
+
20
+ - README updated
21
+ - Rakefile cleaned up. You can now just run `rake` which will run specs and fix linting using `standardrb`
22
+ - Small documentation clarification [@smnscp](https://github.com/smnscp)
23
+ - Bump `rqrcode_core` to `~> 1.0`
24
+
25
+ ### Breaking Change
26
+
27
+ - The dependency `rqrcode_core-1.0.0` has a tiny breaking change to the `to_s` public method. https://github.com/whomwah/rqrcode_core/blob/master/CHANGELOG.md#breaking-changes
28
+
29
+ ## [1.2.0] - 2020-12-26
30
+
31
+ ### Changed
32
+
33
+ - README updated
34
+ - bump dependencies
35
+ - fix `required_ruby_version` for Ruby 3 support
36
+
37
+ [unreleased]: https://github.com/whomwah/rqrcode/compare/v2.0.0...HEAD
38
+ [2.0.0]: https://github.com/whomwah/rqrcode/compare/v1.2.0...v2.0.0
39
+ [1.2.0]: https://github.com/whomwah/rqrcode/compare/v1.1.1...v1.2.0
data/Gemfile.lock ADDED
@@ -0,0 +1,68 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ rqrcode (2.0.0)
5
+ chunky_png (~> 1.0)
6
+ rqrcode_core (~> 1.0)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ ast (2.4.2)
12
+ chunky_png (1.4.0)
13
+ diff-lcs (1.4.4)
14
+ parallel (1.20.1)
15
+ parser (3.0.1.0)
16
+ ast (~> 2.4.1)
17
+ rainbow (3.0.0)
18
+ rake (13.0.3)
19
+ regexp_parser (2.1.1)
20
+ rexml (3.2.5)
21
+ rqrcode_core (1.0.0)
22
+ rspec (3.10.0)
23
+ rspec-core (~> 3.10.0)
24
+ rspec-expectations (~> 3.10.0)
25
+ rspec-mocks (~> 3.10.0)
26
+ rspec-core (3.10.1)
27
+ rspec-support (~> 3.10.0)
28
+ rspec-expectations (3.10.1)
29
+ diff-lcs (>= 1.2.0, < 2.0)
30
+ rspec-support (~> 3.10.0)
31
+ rspec-mocks (3.10.2)
32
+ diff-lcs (>= 1.2.0, < 2.0)
33
+ rspec-support (~> 3.10.0)
34
+ rspec-support (3.10.2)
35
+ rubocop (1.12.1)
36
+ parallel (~> 1.10)
37
+ parser (>= 3.0.0.0)
38
+ rainbow (>= 2.2.2, < 4.0)
39
+ regexp_parser (>= 1.8, < 3.0)
40
+ rexml
41
+ rubocop-ast (>= 1.2.0, < 2.0)
42
+ ruby-progressbar (~> 1.7)
43
+ unicode-display_width (>= 1.4.0, < 3.0)
44
+ rubocop-ast (1.4.1)
45
+ parser (>= 2.7.1.5)
46
+ rubocop-performance (1.10.1)
47
+ rubocop (>= 0.90.0, < 2.0)
48
+ rubocop-ast (>= 0.4.0)
49
+ ruby-progressbar (1.11.0)
50
+ standard (1.0.5)
51
+ rubocop (= 1.12.1)
52
+ rubocop-performance (= 1.10.1)
53
+ standardrb (1.0.0)
54
+ standard
55
+ unicode-display_width (2.0.0)
56
+
57
+ PLATFORMS
58
+ ruby
59
+
60
+ DEPENDENCIES
61
+ bundler (~> 2.0)
62
+ rake (~> 13.0)
63
+ rqrcode!
64
+ rspec (~> 3.5)
65
+ standardrb (~> 1.0)
66
+
67
+ BUNDLED WITH
68
+ 2.2.15
data/README.md CHANGED
@@ -1,20 +1,21 @@
1
1
  # RQRCode
2
2
 
3
- ![](https://github.com/whomwah/rqrcode/workflows/rqrcode/badge.svg)
3
+ ![](https://github.com/whomwah/rqrcode/actions/workflows/ruby.yml/badge.svg)
4
4
 
5
5
 
6
6
  [RQRCode](https://github.com/whomwah/rqrcode) is a library for creating and rendering QR codes into various formats. It has a simple interface with all the standard QR code options. It was adapted from the Javascript library by Kazuhiko Arase.
7
7
 
8
8
  * QR code is trademarked by Denso Wave inc
9
- * Minimum Ruby version is `~> 2.3`
10
- * For `rqrcode` releases `< 1.0.0` please use [this README](https://github.com/whomwah/rqrcode/blob/cd2732a68434e6197c219e6c8cbdadfce0c4c4f3/README.md)
9
+ * Minimum Ruby version is `>= 2.3`
10
+ * For `rqrcode` releases `< 2.0.0` please use [this README](https://github.com/whomwah/rqrcode/blob/v1.2.0/README.md)
11
+ * For `rqrcode` releases `< 1.0.0` please use [this README](https://github.com/whomwah/rqrcode/blob/v0.9.0/README.md)
11
12
 
12
13
  ## Installing
13
14
 
14
15
  Add this line to your application's `Gemfile`:
15
16
 
16
17
  ```ruby
17
- gem 'rqrcode'
18
+ gem "rqrcode", "~> 2.0"
18
19
  ```
19
20
 
20
21
  or install manually:
@@ -26,20 +27,19 @@ gem install rqrcode
26
27
  ## Basic usage example
27
28
 
28
29
  ```ruby
29
- require 'rqrcode'
30
+ require "rqrcode"
30
31
 
31
- qr = RQRCode::QRCode.new('http://github.com')
32
- result = ''
32
+ qr = RQRCode::QRCode.new("https://kyan.com")
33
33
 
34
- qr.qrcode.modules.each do |row|
35
- row.each do |col|
36
- result << (col ? 'X' : 'O')
37
- end
38
-
39
- result << "\n"
40
- end
34
+ puts qr.to_s
41
35
 
42
- puts result
36
+ xxxxxxx xxxxxxx xxx xxxxxxx
37
+ x x x xxx xx x x
38
+ x xxx x xx x x xx x xxx x
39
+ x xxx x xx xx xx x xxx x
40
+ x xxx x x x xxx x xxx x
41
+ x x xxx x xx x x x x
42
+ ...
43
43
  ```
44
44
 
45
45
  ### Advanced Options
@@ -49,7 +49,7 @@ These are the various QR Code generation options provided by [rqrqcode_core](htt
49
49
  ```
50
50
  string - the string you wish to encode
51
51
 
52
- size - the size of the qrcode (default 4)
52
+ size - the size (Integer) of the qrcode (defaults to smallest size needed to encode the string)
53
53
 
54
54
  level - the error correction level, can be:
55
55
  * Level :l 7% of code can be restored
@@ -72,104 +72,207 @@ qrcode = RQRCodeCore::QRCode.new('hello world', size: 1, level: :m, mode: :alpha
72
72
 
73
73
  ## Render types
74
74
 
75
- You can output your QR code in various forms. These are detailed below:
75
+ You probably want to output your QR code in a specific format. We make this easy by providing a bunch of formats to choose from below, each with their own set of options:
76
76
 
77
- ### as SVG
77
+ ### `as_svg`
78
78
 
79
79
  The SVG renderer will produce a stand-alone SVG as a `String`
80
80
 
81
+ ```
82
+ Options:
83
+
84
+ offset - Padding around the QR Code in pixels
85
+ (default 0)
86
+ fill - Background color e.g "ffffff" or :white
87
+ (default none)
88
+ color - Foreground color e.g "000" or :black
89
+ (default "000")
90
+ module_size - The Pixel size of each module
91
+ (defaults 11)
92
+ shape_rendering - SVG Attribute: auto | optimizeSpeed | crispEdges | geometricPrecision
93
+ (defaults crispEdges)
94
+ standalone - Whether to make this a full SVG file, or only an svg to embed in other svg
95
+ (default true)
96
+ use_path - Use <path> to render SVG rather than <rect> to significantly reduce size
97
+ and quality. This will become the default in future versions.
98
+ (default false)
99
+ viewbox - Replace the `svg.width` and `svg.height` attribute with `svg.viewBox` to
100
+ allow CSS scaling
101
+ (default false)
102
+ svg_attributes - A optional hash of custom <svg> attributes. Existing attributes will remain.
103
+ (default {})
104
+ ```
105
+ Example
81
106
  ```ruby
82
- require 'rqrcode'
107
+ require "rqrcode"
83
108
 
84
109
  qrcode = RQRCode::QRCode.new("http://github.com/")
85
110
 
86
111
  # NOTE: showing with default options specified explicitly
87
112
  svg = qrcode.as_svg(
88
- offset: 0,
89
- color: '000',
90
- shape_rendering: 'crispEdges',
91
- module_size: 6,
92
- standalone: true
113
+ color: "000",
114
+ shape_rendering: "crispEdges",
115
+ module_size: 11,
116
+ standalone: true,
117
+ use_path: true,
118
+ svg_attributes: {
119
+ id: "myUniqueId"
120
+ }
93
121
  )
94
122
  ```
95
123
 
96
124
  ![QR code with github url](./images/github-qrcode.svg)
97
125
 
98
- ### as ANSI
126
+ ### `as_png`
99
127
 
100
- The ANSI renderer will produce as a string with ANSI color codes.
128
+ The will produce a PNG using the [ChunkyPNG gem](https://github.com/wvanbergen/chunky_png). The result will be a `ChunkyPNG::Image` instance.
101
129
 
102
- ```ruby
103
- require 'rqrcode'
130
+ ```
131
+ Options:
104
132
 
105
- qrcode = RQRCode::QRCode.new("http://github.com/")
133
+ fill - Background ChunkyPNG::Color, defaults to 'white'
134
+ color - Foreground ChunkyPNG::Color, defaults to 'black'
106
135
 
107
- # NOTE: showing with default options specified explicitly
108
- svg = qrcode.as_ansi(
109
- light: "\033[47m", dark: "\033[40m",
110
- fill_character: ' ',
111
- quiet_zone_size: 4
112
- )
113
- ```
136
+ When option :file is supplied you can use the following ChunkyPNG constraints:
114
137
 
115
- ![QR code with github url](./images/ansi-screen-shot.png)
138
+ color_mode - The color mode to use. Use one of the ChunkyPNG::COLOR_* constants.
139
+ (defaults to 'ChunkyPNG::COLOR_GRAYSCALE')
140
+ bit_depth - The bit depth to use. This option is only used for indexed images.
141
+ (defaults to 1 bit)
142
+ interlace - Whether to use interlacing (true or false).
143
+ (defaults to ChunkyPNG default)
144
+ compression - The compression level for Zlib. This can be a value between 0 and 9, or a
145
+ Zlib constant like Zlib::BEST_COMPRESSION
146
+ (defaults to ChunkyPNG default)
116
147
 
117
- ### as PNG
148
+ There are two sizing algorithms.
118
149
 
119
- The library can produce a PNG. Result will be a `ChunkyPNG::Image` instance.
150
+ * Original that can result in blurry and hard to scan images
151
+ * Google's Chart API inspired sizing that resizes the module size to fit within the given image size.
152
+
153
+ The Google one will be used when no options are given or when the new size option is used.
154
+
155
+ *Google Sizing*
156
+
157
+ size - Total size of PNG in pixels. The module size is calculated so it fits.
158
+ (defaults to 120)
159
+ border_modules - Width of white border around the modules.
160
+ (defaults to 4).
161
+
162
+ -- DONT USE border_modules OPTION UNLESS YOU KNOW ABOUT THE QUIET ZONE NEEDS OF QR CODES --
163
+
164
+ *Original Sizing*
165
+
166
+ module_px_size - Image size, in pixels.
167
+ border - Border thickness, in pixels
168
+
169
+ It first creates an image where 1px = 1 module, then resizes.
170
+ Defaults to 120x120 pixels, customizable by option.
171
+ ```
172
+
173
+ Example
120
174
 
121
175
  ```ruby
122
- require 'rqrcode'
176
+ require "rqrcode"
123
177
 
124
178
  qrcode = RQRCode::QRCode.new("http://github.com/")
125
179
 
126
180
  # NOTE: showing with default options specified explicitly
127
181
  png = qrcode.as_png(
128
- resize_gte_to: false,
129
- resize_exactly_to: false,
130
- fill: 'white',
131
- color: 'black',
132
- size: 120,
182
+ bit_depth: 1,
133
183
  border_modules: 4,
184
+ color_mode: ChunkyPNG::COLOR_GRAYSCALE,
185
+ color: "black",
186
+ file: nil,
187
+ fill: "white",
134
188
  module_px_size: 6,
135
- file: nil # path to write
189
+ resize_exactly_to: false,
190
+ resize_gte_to: false,
191
+ size: 120
136
192
  )
137
193
 
138
- IO.write("/tmp/github-qrcode.png", png.to_s)
194
+ IO.binwrite("/tmp/github-qrcode.png", png.to_s)
139
195
  ```
140
196
 
141
197
  ![QR code with github url](./images/github-qrcode.png)
142
198
 
143
- ### On the console ( just because you can )
144
199
 
145
- ```ruby
146
- require 'rqrcode'
200
+ ### `as_ansi`
147
201
 
148
- qr = RQRCode::QRCode.new('http://kyan.com', size: 4, level: :h)
202
+ The ANSI renderer will produce as a string with ANSI color codes.
149
203
 
150
- puts qr.to_s
151
204
  ```
205
+ Options:
206
+
207
+ light - Foreground ANSI code
208
+ (default "\033[47m")
209
+ dark - Background ANSI code
210
+ (default "\033[40m")
211
+ fill_character - The written character
212
+ (default ' ')
213
+ quiet_zone_size - Padding around the edge
214
+ (default 4)
215
+ ```
216
+ Example
217
+ ```ruby
218
+ require "rqrcode"
152
219
 
153
- Output:
220
+ qrcode = RQRCode::QRCode.new("http://github.com/")
154
221
 
222
+ # NOTE: showing with default options specified explicitly
223
+ svg = qrcode.as_ansi(
224
+ light: "\033[47m", dark: "\033[40m",
225
+ fill_character: " ",
226
+ quiet_zone_size: 4
227
+ )
155
228
  ```
156
- xxxxxxx x x xxx xxxxxxx
157
- x x xxxxx x x x x
158
- x xxx x x x x x xxx x
159
- x xxx x xxx x xxx x xxx x
160
- x xxx x xxx x x x x xxx x
161
- ... etc
162
- ```
229
+
230
+ ![QR code with github url](./images/ansi-screen-shot.png)
163
231
 
164
232
  ## API Documentation
165
233
 
166
234
  [http://www.rubydoc.info/gems/rqrcode](http://www.rubydoc.info/gems/rqrcode)
167
235
 
236
+ ## Tests
237
+
238
+ You can run the test suite using:
239
+
240
+ ```
241
+ $ ./bin/setup
242
+ $ rake # runs specs and standard:fix
243
+ $ rake spec # just runs the specs
244
+ ```
245
+
246
+ or try the lib from the console with:
247
+
248
+ ```
249
+ $ ./bin/console
250
+ ```
251
+
252
+ ## Linting
253
+
254
+ The project uses [standardrb](https://github.com/testdouble/standard) and can be used with:
255
+
256
+ ```
257
+ $ ./bin/setup
258
+ $ rake standard # checks
259
+ $ rake standard:fix # fixes
260
+ ```
261
+
168
262
  ## Contributing
263
+
264
+ I am not currently accepting any new renderers as the current `as_png`, `as_svg` and `as_ansi` work for most cases. If you need something different from what's available, the [`rqrcode_core`](https://github.com/whomwah/rqrcode_core) gem gives you access to all the QR Code information you will need so makes it simple to generate your own.
265
+
266
+ The motivation for the above is because the rendering side of this gem takes up the most time. It seems that many people want a slightly different version of a QR Code so supporting all the variations would be hard. The easiest way is to empower people to create their own versions which they can manage and share. This is what `rqrcode_core` does.
267
+
268
+ Any contribution PR's will be greatly accepted. It's important that they are well tested and backwards compatible.
269
+
169
270
  * Fork the project
170
271
  * Send a pull request
171
272
  * Don't touch the .gemspec, I'll do that when I release a new version
172
273
 
274
+ Thanks D.
275
+
173
276
  ## Authors
174
277
 
175
278
  Original RQRCode author: Duncan Robertson
data/Rakefile CHANGED
@@ -1,10 +1,10 @@
1
- require "bundler/gem_tasks"
2
- require "rake/testtask"
1
+ begin
2
+ require "standard/rake"
3
+ require "rspec/core/rake_task"
3
4
 
4
- Rake::TestTask.new(:test) do |t|
5
- t.libs << "test"
6
- t.libs << "lib"
7
- t.test_files = FileList["test/**/*_test.rb"]
8
- end
5
+ RSpec::Core::RakeTask.new(:spec)
9
6
 
10
- task :default => :test
7
+ task default: [:spec, "standard:fix"]
8
+ rescue LoadError
9
+ # no standard/rspec available
10
+ end
data/lib/rqrcode.rb CHANGED
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RQRCode
4
- require 'rqrcode_core'
5
- require 'rqrcode/qrcode'
6
- require 'rqrcode/export'
7
- require 'rqrcode/version'
4
+ require "rqrcode_core"
5
+ require "rqrcode/qrcode"
6
+ require "rqrcode/export"
7
+ require "rqrcode/version"
8
8
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'rqrcode/export/ansi'
4
- require 'rqrcode/export/html'
5
- require 'rqrcode/export/png'
6
- require 'rqrcode/export/svg'
3
+ require "rqrcode/export/ansi"
4
+ require "rqrcode/export/html"
5
+ require "rqrcode/export/png"
6
+ require "rqrcode/export/svg"
@@ -9,15 +9,15 @@ module RQRCode
9
9
  #
10
10
  # Options:
11
11
  # light: Foreground ("\033[47m")
12
- # dark: Background ANSI code. ("\033[47m")
12
+ # dark: Background ANSI code. ("\033[40m")
13
13
  # fill_character: The written character. (' ')
14
14
  # quiet_zone_size: (4)
15
15
  #
16
- def as_ansi(options={})
16
+ def as_ansi(options = {})
17
17
  options = {
18
18
  light: "\033[47m",
19
19
  dark: "\033[40m",
20
- fill_character: ' ',
20
+ fill_character: " ",
21
21
  quiet_zone_size: 4
22
22
  }.merge(options)
23
23
 
@@ -39,15 +39,13 @@ module RQRCode
39
39
  row << dark
40
40
  previous_dark = true
41
41
  end
42
- row << fill_character
43
- else
42
+ elsif previous_dark != false
44
43
  # light
45
- if previous_dark != false
46
- row << light
47
- previous_dark = false
48
- end
49
- row << fill_character
44
+ row << light
45
+ previous_dark = false
50
46
  end
47
+
48
+ row << fill_character
51
49
  end
52
50
 
53
51
  # add quiet zone
@@ -68,7 +66,7 @@ module RQRCode
68
66
  quiet_row = light + fill_character * width + normal
69
67
  quiet_rows = quiet_row * quiet_zone_size
70
68
 
71
- return quiet_rows + output.join + quiet_rows
69
+ quiet_rows + output.join + quiet_rows
72
70
  end
73
71
  end
74
72
  end
@@ -6,7 +6,7 @@ module RQRCode
6
6
  #
7
7
  # Use this module to HTML-ify the QR code if you just want the default HTML
8
8
  def as_html
9
- ['<table>', rows.as_html, '</table>'].join
9
+ ["<table>", rows.as_html, "</table>"].join
10
10
  end
11
11
 
12
12
  private
@@ -27,7 +27,7 @@ module RQRCode
27
27
 
28
28
  class Row < Struct.new(:qr, :qr_module, :row_index)
29
29
  def as_html
30
- ['<tr>', cells.map(&:as_html).join, '</tr>'].join
30
+ ["<tr>", cells.map(&:as_html).join, "</tr>"].join
31
31
  end
32
32
 
33
33
  def cells
@@ -41,7 +41,7 @@ module RQRCode
41
41
  end
42
42
 
43
43
  def html_class
44
- qr.checked?(row_index, col_index) ? 'black' : 'white'
44
+ qr.checked?(row_index, col_index) ? "black" : "white"
45
45
  end
46
46
  end
47
47
  end
@@ -1,58 +1,70 @@
1
1
  # frozen_string_literal: true
2
- require 'chunky_png'
2
+
3
+ require "chunky_png"
3
4
 
4
5
  # This class creates PNG files.
5
6
  # Code from: https://github.com/DCarper/rqrcode
6
7
  module RQRCode
7
8
  module Export
8
9
  module PNG
10
+ # Render the PNG from the QR Code.
9
11
  #
10
- # Render the PNG from the Qrcode.
12
+ # Options:
13
+ # fill - Background ChunkyPNG::Color, defaults to 'white'
14
+ # color - Foreground ChunkyPNG::Color, defaults to 'black'
11
15
  #
12
- # There are two sizing algoritams.
16
+ # When option :file is supplied you can use the following ChunkyPNG constraints
17
+ # color_mode - The color mode to use. Use one of the ChunkyPNG::COLOR_* constants.
18
+ # (defaults to 'ChunkyPNG::COLOR_GRAYSCALE')
19
+ # bit_depth - The bit depth to use. This option is only used for indexed images.
20
+ # (defaults to 1 bit)
21
+ # interlace - Whether to use interlacing (true or false).
22
+ # (defaults to ChunkyPNG default)
23
+ # compression - The compression level for Zlib. This can be a value between 0 and 9, or a
24
+ # Zlib constant like Zlib::BEST_COMPRESSION
25
+ # (defaults to ChunkyPNG default)
26
+ #
27
+ # There are two sizing algorithms.
13
28
  #
14
29
  # - Original that can result in blurry and hard to scan images
15
30
  # - Google's Chart API inspired sizing that resizes the module size to fit within the given image size.
16
31
  #
17
32
  # The Googleis one will be used when no options are given or when the new size option is used.
18
33
  #
19
- # Options:
20
- # fill - Background ChunkyPNG::Color, defaults to 'white'
21
- # color - Foreground ChunkyPNG::Color, defaults to 'black'
22
- #
23
- # *Googleis*
24
- # size - Total size of PNG in pixels. The module size is calculated so it fits. (defaults to 90)
25
- # border_modules - Width of white border around in modules. (defaults to 4).
34
+ # *Google*
35
+ # size - Total size of PNG in pixels. The module size is calculated so it fits.
36
+ # (defaults to 120)
37
+ # border_modules - Width of white border around in modules.
38
+ # (defaults to 4).
26
39
  #
27
40
  # -- DONT USE border_modules OPTION UNLESS YOU KNOW ABOUT THE QUIET ZONE NEEDS OF QR CODES --
28
41
  #
29
42
  # *Original*
30
43
  # module_px_size - Image size, in pixels.
31
- # border - Border thickness, in pixels
44
+ # border - Border thickness, in pixels
32
45
  #
33
46
  # It first creates an image where 1px = 1 module, then resizes.
34
- # Defaults to 90x90 pixels, customizable by option.
47
+ # Defaults to 120x120 pixels, customizable by option.
35
48
  #
36
49
  def as_png(options = {})
37
50
  default_img_options = {
38
- :resize_gte_to => false,
39
- :resize_exactly_to => false,
40
- :fill => 'white',
41
- :color => 'black',
42
- :size => 120,
43
- :border_modules => 4,
44
- :file => false,
45
- :module_px_size => 6
51
+ bit_depth: 1,
52
+ border_modules: 4,
53
+ color_mode: ChunkyPNG::COLOR_GRAYSCALE,
54
+ color: "black",
55
+ file: false,
56
+ fill: "white",
57
+ module_px_size: 6,
58
+ resize_exactly_to: false,
59
+ resize_gte_to: false,
60
+ size: 120
46
61
  }
47
62
 
48
- googleis = options.length == 0 || (options[:size] != nil)
49
-
63
+ googleis = options.length == 0 || !options[:size].nil?
50
64
  options = default_img_options.merge(options) # reverse_merge
51
-
52
- fill = ChunkyPNG::Color(options[:fill])
53
- color = ChunkyPNG::Color(options[:color])
65
+ fill = ChunkyPNG::Color(options[:fill])
66
+ color = ChunkyPNG::Color(options[:color])
54
67
  output_file = options[:file]
55
-
56
68
  module_px_size = nil
57
69
  border_px = nil
58
70
  png = nil
@@ -77,7 +89,7 @@ module RQRCode
77
89
  else
78
90
  options[:module_px_size]
79
91
  end
80
- border_px = border * module_px_size
92
+ border_px = border * module_px_size
81
93
  total_border_px = border_px * 2
82
94
  resize_to = options[:resize_exactly_to]
83
95
 
@@ -92,7 +104,7 @@ module RQRCode
92
104
  if @qrcode.checked?(x, y)
93
105
  (0...module_px_size).each do |i|
94
106
  (0...module_px_size).each do |j|
95
- png[(y * module_px_size) + border_px + j , (x * module_px_size) + border_px + i] = color
107
+ png[(y * module_px_size) + border_px + j, (x * module_px_size) + border_px + i] = color
96
108
  end
97
109
  end
98
110
  end
@@ -103,10 +115,16 @@ module RQRCode
103
115
  png = png.resize(resize_to, resize_to)
104
116
  end
105
117
 
106
-
107
118
  if output_file
108
- png.save(output_file,{ :color_mode => ChunkyPNG::COLOR_GRAYSCALE, :bit_depth =>1})
119
+ constraints = {
120
+ color_mode: options[:color_mode],
121
+ bit_depth: options[:bit_depth]
122
+ }
123
+ constraints[:interlace] = options[:interlace] if options.has_key?(:interlace)
124
+ constraints[:compression] = options[:compression] if options.has_key?(:compression)
125
+ png.save(output_file, constraints)
109
126
  end
127
+
110
128
  png
111
129
  end
112
130
  end
@@ -1,59 +1,198 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # This class creates a SVG files.
4
- # Code from: https://github.com/samvincent/rqrcode-rails3
4
+ # Initial code from: https://github.com/samvincent/rqrcode-rails3
5
5
  module RQRCode
6
6
  module Export
7
7
  module SVG
8
+ class BaseOutputSVG
9
+ attr_reader :result
10
+
11
+ def initialize(qrcode)
12
+ @qrcode = qrcode
13
+ @result = []
14
+ end
15
+ end
16
+
17
+ class Path < BaseOutputSVG
18
+ def build(module_size, offset, color)
19
+ modules_array = @qrcode.modules
20
+ matrix_width = matrix_height = modules_array.length + 1
21
+ empty_row = [Array.new(matrix_width - 1, false)]
22
+ edge_matrix = Array.new(matrix_height) { Array.new(matrix_width) }
23
+
24
+ (empty_row + modules_array + empty_row).each_cons(2).with_index do |row_pair, row_index|
25
+ first_row, second_row = row_pair
26
+
27
+ # horizontal edges
28
+ first_row.zip(second_row).each_with_index do |cell_pair, column_index|
29
+ edge = case cell_pair
30
+ when [true, false] then Edge.new column_index + 1, row_index, :left
31
+ when [false, true] then Edge.new column_index, row_index, :right
32
+ end
33
+
34
+ (edge_matrix[edge.start_y][edge.start_x] ||= []) << edge if edge
35
+ end
36
+
37
+ # vertical edges
38
+ ([false] + second_row + [false]).each_cons(2).each_with_index do |cell_pair, column_index|
39
+ edge = case cell_pair
40
+ when [true, false] then Edge.new column_index, row_index, :down
41
+ when [false, true] then Edge.new column_index, row_index + 1, :up
42
+ end
43
+
44
+ (edge_matrix[edge.start_y][edge.start_x] ||= []) << edge if edge
45
+ end
46
+ end
47
+
48
+ edge_count = edge_matrix.flatten.compact.count
49
+ path = []
50
+
51
+ while edge_count > 0
52
+ edge_loop = []
53
+ next_matrix_cell = edge_matrix.find(&:any?).find { |cell| cell&.any? }
54
+ edge = next_matrix_cell.first
55
+
56
+ while edge
57
+ edge_loop << edge
58
+ matrix_cell = edge_matrix[edge.start_y][edge.start_x]
59
+ matrix_cell.delete edge
60
+ edge_matrix[edge.start_y][edge.start_x] = nil if matrix_cell.empty?
61
+ edge_count -= 1
62
+
63
+ # try to find an edge continuing the current edge
64
+ edge = edge_matrix[edge.end_y][edge.end_x]&.first
65
+ end
66
+
67
+ first_edge = edge_loop.first
68
+ edge_loop_string = SVG_PATH_COMMANDS[:move]
69
+ edge_loop_string += "#{first_edge.start_x} #{first_edge.start_y}"
70
+
71
+ edge_loop.chunk(&:direction).to_a[0...-1].each do |direction, edges|
72
+ edge_loop_string << "#{SVG_PATH_COMMANDS[direction]}#{edges.length}"
73
+ end
74
+ edge_loop_string << SVG_PATH_COMMANDS[:close]
75
+
76
+ path << edge_loop_string
77
+ end
78
+
79
+ @result << %{<path d="#{path.join}" style="fill:##{color}" transform="translate(#{offset},#{offset}) scale(#{module_size})"/>}
80
+ end
81
+ end
82
+
83
+ class Rect < BaseOutputSVG
84
+ def build(module_size, offset, color)
85
+ @qrcode.modules.each_index do |c|
86
+ tmp = []
87
+ @qrcode.modules.each_index do |r|
88
+ y = c * module_size + offset
89
+ x = r * module_size + offset
90
+
91
+ next unless @qrcode.checked?(c, r)
92
+ tmp << %(<rect width="#{module_size}" height="#{module_size}" x="#{x}" y="#{y}" style="fill:##{color}"/>)
93
+ end
94
+
95
+ @result << tmp.join
96
+ end
97
+ end
98
+ end
99
+
100
+ class Edge < Struct.new(:start_x, :start_y, :direction)
101
+ def end_x
102
+ case direction
103
+ when :right then start_x + 1
104
+ when :left then start_x - 1
105
+ else start_x
106
+ end
107
+ end
108
+
109
+ def end_y
110
+ case direction
111
+ when :down then start_y + 1
112
+ when :up then start_y - 1
113
+ else start_y
114
+ end
115
+ end
116
+ end
117
+
118
+ DEFAULT_SVG_ATTRIBUTES = [
119
+ %(version="1.1"),
120
+ %(xmlns="http://www.w3.org/2000/svg"),
121
+ %(xmlns:xlink="http://www.w3.org/1999/xlink"),
122
+ %(xmlns:ev="http://www.w3.org/2001/xml-events")
123
+ ]
124
+
125
+ SVG_PATH_COMMANDS = {
126
+ move: "M",
127
+ up: "v-",
128
+ down: "v",
129
+ left: "h-",
130
+ right: "h",
131
+ close: "z"
132
+ }
133
+
8
134
  #
9
135
  # Render the SVG from the Qrcode.
10
136
  #
11
137
  # Options:
12
- # offset - Padding around the QR Code (e.g. 10)
13
- # fill - Background color (e.g "ffffff" or :white)
14
- # color - Foreground color for the code (e.g. "000000" or :black)
15
- # module_size - The Pixel size of each module (e.g. 11)
16
- # shape_rendering - Defaults to crispEdges
17
- # standalone - wether to make this a full SVG file, or only svg to embed
18
- # in other svg.
138
+ # offset - Padding around the QR Code in pixels
139
+ # (default 0)
140
+ # fill - Background color e.g "ffffff"
141
+ # (default none)
142
+ # color - Foreground color e.g "000"
143
+ # (default "000")
144
+ # module_size - The Pixel size of each module
145
+ # (defaults 11)
146
+ # shape_rendering - SVG Attribute: auto | optimizeSpeed | crispEdges | geometricPrecision
147
+ # (defaults crispEdges)
148
+ # standalone - Whether to make this a full SVG file, or only an svg to embed in other svg
149
+ # (default true)
150
+ # use_path - Use <path> to render SVG rather than <rect> to significantly reduce size
151
+ # and quality. This will become the default in future versions.
152
+ # (default false)
153
+ # viewbox - replace `width` and `height` in <svg> with a viewBox, allows CSS scaling
154
+ # (default false)
155
+ # svg_attributes - A optional hash of custom <svg> attributes. Existing attributes will remain.
156
+ # (default {})
19
157
  #
20
- def as_svg(options={})
158
+ def as_svg(options = {})
159
+ fill = options[:fill]
160
+ use_path = options[:use_path]
21
161
  offset = options[:offset].to_i || 0
22
162
  color = options[:color] || "000"
23
163
  shape_rendering = options[:shape_rendering] || "crispEdges"
24
164
  module_size = options[:module_size] || 11
25
165
  standalone = options[:standalone].nil? ? true : options[:standalone]
166
+ viewbox = options[:viewbox].nil? ? false : options[:viewbox]
167
+ svg_attributes = options[:svg_attributes] || {}
26
168
 
27
169
  # height and width dependent on offset and QR complexity
28
- dimension = (@qrcode.module_count*module_size) + (2*offset)
170
+ dimension = (@qrcode.module_count * module_size) + (2 * offset)
171
+ # use dimensions differently if we are using a viewBox
172
+ dimensions_attr = viewbox ? %(viewBox="0 0 #{dimension} #{dimension}") : %(width="#{dimension}" height="#{dimension}")
29
173
 
30
- xml_tag = %{<?xml version="1.0" standalone="yes"?>}
31
- open_tag = %{<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events" width="#{dimension}" height="#{dimension}" shape-rendering="#{shape_rendering}">}
32
- close_tag = "</svg>"
174
+ svg_tag_attributes = (DEFAULT_SVG_ATTRIBUTES + [
175
+ dimensions_attr,
176
+ %(shape-rendering="#{shape_rendering}")
177
+ ] + svg_attributes.map { |k, v| %(#{k}="#{v}") }).join(" ")
33
178
 
34
- result = []
35
- @qrcode.modules.each_index do |c|
36
- tmp = []
37
- @qrcode.modules.each_index do |r|
38
- y = c*module_size + offset
39
- x = r*module_size + offset
179
+ xml_tag = %(<?xml version="1.0" standalone="yes"?>)
180
+ open_tag = %(<svg #{svg_tag_attributes}>)
181
+ close_tag = "</svg>"
40
182
 
41
- next unless @qrcode.checked?(c, r)
42
- tmp << %{<rect width="#{module_size}" height="#{module_size}" x="#{x}" y="#{y}" style="fill:##{color}"/>}
43
- end
44
- result << tmp.join
45
- end
183
+ output_tag = (use_path ? Path : Rect).new(@qrcode)
184
+ output_tag.build(module_size, offset, color)
46
185
 
47
- if options[:fill]
48
- result.unshift %{<rect width="#{dimension}" height="#{dimension}" x="0" y="0" style="fill:##{options[:fill]}"/>}
186
+ if fill
187
+ output_tag.result.unshift %(<rect width="#{dimension}" height="#{dimension}" x="0" y="0" style="fill:##{fill}"/>)
49
188
  end
50
189
 
51
190
  if standalone
52
- result.unshift(xml_tag, open_tag)
53
- result << close_tag
191
+ output_tag.result.unshift(xml_tag, open_tag)
192
+ output_tag.result << close_tag
54
193
  end
55
194
 
56
- result.join("\n")
195
+ output_tag.result.join
57
196
  end
58
197
  end
59
198
  end
@@ -1,3 +1,3 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'rqrcode/qrcode/qrcode'
3
+ require "rqrcode/qrcode/qrcode"
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'forwardable'
3
+ require "forwardable"
4
4
 
5
5
  module RQRCode #:nodoc:
6
6
  class QRCode
@@ -11,7 +11,7 @@ module RQRCode #:nodoc:
11
11
  attr_reader :qrcode
12
12
 
13
13
  def initialize(string, *args)
14
- @qrcode = RQRCodeCore::QRCode.new(string, args)
14
+ @qrcode = RQRCodeCore::QRCode.new(string, *args)
15
15
  end
16
16
  end
17
17
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RQRCode
4
- VERSION = "1.0.0"
4
+ VERSION = "2.0.0"
5
5
  end
data/rqrcode.gemspec CHANGED
@@ -1,36 +1,35 @@
1
- # -*- encoding: utf-8 -*-
2
-
3
1
  lib = File.expand_path("../lib", __FILE__)
4
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
3
  require "rqrcode/version"
6
4
 
7
5
  Gem::Specification.new do |spec|
8
- spec.name = "rqrcode"
9
- spec.version = RQRCode::VERSION
10
- spec.platform = Gem::Platform::RUBY
11
- spec.authors = ["Duncan Robertson"]
12
- spec.email = ["duncan@whomwah.com"]
6
+ spec.name = "rqrcode"
7
+ spec.version = RQRCode::VERSION
8
+ spec.platform = Gem::Platform::RUBY
9
+ spec.authors = ["Duncan Robertson"]
10
+ spec.email = ["duncan@whomwah.com"]
13
11
 
14
- spec.summary = %q{A library to encode QR Codes}
15
- spec.description = <<EOF
16
- rqrcode is a library for encoding QR Codes. The simple
17
- interface allows you to create QR Code data structures
18
- and then render them in the way you choose.
19
- EOF
20
- spec.homepage = "https://github.com/whomwah/rqrcode"
21
- spec.license = "MIT"
12
+ spec.summary = "A library to encode QR Codes"
13
+ spec.description = <<~EOF
14
+ rqrcode is a library for encoding QR Codes. The simple
15
+ interface allows you to create QR Code data structures
16
+ and then render them in the way you choose.
17
+ EOF
18
+ spec.homepage = "https://github.com/whomwah/rqrcode"
19
+ spec.license = "MIT"
22
20
 
23
- spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
21
+ spec.files = Dir.chdir(File.expand_path("..", __FILE__)) do
24
22
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
25
23
  end
26
- spec.bindir = "exe"
27
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
24
+ spec.bindir = "exe"
25
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
26
  spec.require_paths = ["lib"]
29
27
 
30
- spec.required_ruby_version = '~> 2.3'
31
- spec.add_dependency 'rqrcode_core', '~> 0.1.0'
32
- spec.add_dependency 'chunky_png', "~> 1.0"
28
+ spec.required_ruby_version = ">= 2.3"
29
+ spec.add_dependency "rqrcode_core", "~> 1.0"
30
+ spec.add_dependency "chunky_png", "~> 1.0"
33
31
  spec.add_development_dependency "bundler", "~> 2.0"
34
- spec.add_development_dependency "rake", "~> 12.0"
35
- spec.add_development_dependency "minitest", "~> 5.0"
32
+ spec.add_development_dependency "rake", "~> 13.0"
33
+ spec.add_development_dependency "rspec", "~> 3.5"
34
+ spec.add_development_dependency "standardrb", "~> 1.0"
36
35
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rqrcode
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Duncan Robertson
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-09-16 00:00:00.000000000 Z
11
+ date: 2021-05-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rqrcode_core
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.1.0
19
+ version: '1.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.1.0
26
+ version: '1.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: chunky_png
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -58,28 +58,42 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '12.0'
61
+ version: '13.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '13.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.5'
62
76
  type: :development
63
77
  prerelease: false
64
78
  version_requirements: !ruby/object:Gem::Requirement
65
79
  requirements:
66
80
  - - "~>"
67
81
  - !ruby/object:Gem::Version
68
- version: '12.0'
82
+ version: '3.5'
69
83
  - !ruby/object:Gem::Dependency
70
- name: minitest
84
+ name: standardrb
71
85
  requirement: !ruby/object:Gem::Requirement
72
86
  requirements:
73
87
  - - "~>"
74
88
  - !ruby/object:Gem::Version
75
- version: '5.0'
89
+ version: '1.0'
76
90
  type: :development
77
91
  prerelease: false
78
92
  version_requirements: !ruby/object:Gem::Requirement
79
93
  requirements:
80
94
  - - "~>"
81
95
  - !ruby/object:Gem::Version
82
- version: '5.0'
96
+ version: '1.0'
83
97
  description: |
84
98
  rqrcode is a library for encoding QR Codes. The simple
85
99
  interface allows you to create QR Code data structures
@@ -92,7 +106,10 @@ extra_rdoc_files: []
92
106
  files:
93
107
  - ".github/workflows/ruby.yml"
94
108
  - ".gitignore"
109
+ - ".rspec"
110
+ - CHANGELOG.md
95
111
  - Gemfile
112
+ - Gemfile.lock
96
113
  - LICENSE.txt
97
114
  - README.md
98
115
  - Rakefile
@@ -122,7 +139,7 @@ require_paths:
122
139
  - lib
123
140
  required_ruby_version: !ruby/object:Gem::Requirement
124
141
  requirements:
125
- - - "~>"
142
+ - - ">="
126
143
  - !ruby/object:Gem::Version
127
144
  version: '2.3'
128
145
  required_rubygems_version: !ruby/object:Gem::Requirement
@@ -131,7 +148,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
131
148
  - !ruby/object:Gem::Version
132
149
  version: '0'
133
150
  requirements: []
134
- rubygems_version: 3.0.1
151
+ rubygems_version: 3.2.15
135
152
  signing_key:
136
153
  specification_version: 4
137
154
  summary: A library to encode QR Codes