paperback 0.0.3 → 0.0.5
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 +5 -5
- data/.github/workflows/tests.yml +46 -0
- data/.rubocop-disables.yml +26 -12
- data/CHANGELOG.md +21 -0
- data/README.md +27 -6
- data/bin/paperback +4 -0
- data/lib/paperback/cli.rb +38 -2
- data/lib/paperback/document.rb +134 -17
- data/lib/paperback/preparer.rb +107 -29
- data/lib/paperback/version.rb +2 -1
- data/lib/paperback.rb +12 -0
- data/paperback.gemspec +10 -7
- data/sorbet/config +3 -0
- data/sorbet/rbi/annotations/rainbow.rbi +269 -0
- data/sorbet/rbi/gems/ast@2.4.2.rbi +584 -0
- data/sorbet/rbi/gems/chunky_png@1.4.0.rbi +4498 -0
- data/sorbet/rbi/gems/coderay@1.1.3.rbi +3426 -0
- data/sorbet/rbi/gems/diff-lcs@1.5.0.rbi +1083 -0
- data/sorbet/rbi/gems/method_source@1.0.0.rbi +272 -0
- data/sorbet/rbi/gems/netrc@0.11.0.rbi +158 -0
- data/sorbet/rbi/gems/parallel@1.22.1.rbi +277 -0
- data/sorbet/rbi/gems/parser@3.2.0.0.rbi +6963 -0
- data/sorbet/rbi/gems/pdf-core@0.4.0.rbi +1682 -0
- data/sorbet/rbi/gems/prawn@1.3.0.rbi +5567 -0
- data/sorbet/rbi/gems/pry@0.14.1.rbi +9990 -0
- data/sorbet/rbi/gems/rainbow@3.1.1.rbi +408 -0
- data/sorbet/rbi/gems/rake@13.0.6.rbi +3023 -0
- data/sorbet/rbi/gems/rbi@0.0.16.rbi +3008 -0
- data/sorbet/rbi/gems/regexp_parser@2.6.1.rbi +3481 -0
- data/sorbet/rbi/gems/rexml@3.2.5.rbi +4717 -0
- data/sorbet/rbi/gems/rqrcode@0.10.1.rbi +617 -0
- data/sorbet/rbi/gems/rspec-core@3.12.0.rbi +10791 -0
- data/sorbet/rbi/gems/rspec-expectations@3.12.1.rbi +8106 -0
- data/sorbet/rbi/gems/rspec-mocks@3.12.1.rbi +5305 -0
- data/sorbet/rbi/gems/rspec-support@3.12.0.rbi +1617 -0
- data/sorbet/rbi/gems/rspec@3.12.0.rbi +88 -0
- data/sorbet/rbi/gems/rubocop-ast@1.24.1.rbi +6617 -0
- data/sorbet/rbi/gems/rubocop@0.93.1.rbi +40848 -0
- data/sorbet/rbi/gems/ruby-progressbar@1.11.0.rbi +1234 -0
- data/sorbet/rbi/gems/sixword@0.4.0.rbi +536 -0
- data/sorbet/rbi/gems/spoom@1.1.15.rbi +2383 -0
- data/sorbet/rbi/gems/subprocess@1.5.6.rbi +391 -0
- data/sorbet/rbi/gems/tapioca@0.10.5.rbi +3207 -0
- data/sorbet/rbi/gems/thor@1.2.1.rbi +3956 -0
- data/sorbet/rbi/gems/ttfunk@1.4.0.rbi +1951 -0
- data/sorbet/rbi/gems/unicode-display_width@1.8.0.rbi +40 -0
- data/sorbet/rbi/gems/unparser@0.6.7.rbi +4524 -0
- data/sorbet/rbi/gems/webrick@1.7.0.rbi +2555 -0
- data/sorbet/rbi/gems/yard-sorbet@0.8.0.rbi +441 -0
- data/sorbet/rbi/gems/yard@0.9.28.rbi +17816 -0
- data/sorbet/tapioca/config.yml +13 -0
- data/sorbet/tapioca/require.rb +4 -0
- data/spec/functional/paperback/cli_spec.rb +195 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/unit/paperback_spec.rb +1 -0
- metadata +91 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: fe9b3003bc8749cbd4c5bd312b2b1d0b7546f9268e0f1c41e94c71f12a62df2c
|
4
|
+
data.tar.gz: d9630db98c97621804f79a951a140d2d9faa5080bc853c7e2492920e58dec07f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 15f5f07874c345f8ed9c0565a7704bf46be836c9d398ba8ec0f39fac6501cd4152762ed257cba92ea3e2f0e1abe223a9aec2a3318e13bc620507ec809033ba30
|
7
|
+
data.tar.gz: e6bbb5beb3ea669e663031ffe8d25088d2657f264fdd7569048f7f3d90264c0954f838025ae4c020c9b28c5971a8ca53669377edf5a731cfff8bcacfcb8fd4eb
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# This workflow uses actions that are not certified by GitHub.
|
2
|
+
# They are provided by a third-party and are governed by
|
3
|
+
# separate terms of service, privacy policy, and support
|
4
|
+
# documentation.
|
5
|
+
# This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
|
6
|
+
# For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
|
7
|
+
|
8
|
+
name: Ruby
|
9
|
+
|
10
|
+
on:
|
11
|
+
- push
|
12
|
+
- pull_request
|
13
|
+
|
14
|
+
permissions:
|
15
|
+
contents: read
|
16
|
+
|
17
|
+
jobs:
|
18
|
+
test:
|
19
|
+
|
20
|
+
runs-on: ubuntu-latest
|
21
|
+
strategy:
|
22
|
+
matrix:
|
23
|
+
ruby-version: ['2.7', '3.0', '3.1', '3.2']
|
24
|
+
|
25
|
+
steps:
|
26
|
+
- uses: actions/checkout@v3
|
27
|
+
|
28
|
+
- name: Install apt dependencies for tests
|
29
|
+
run: |
|
30
|
+
sudo apt-get update -y
|
31
|
+
sudo apt-get install poppler-utils
|
32
|
+
|
33
|
+
- name: Set up Ruby
|
34
|
+
# To automatically get bug fixes and new Ruby versions for ruby/setup-ruby,
|
35
|
+
# change this to (see https://github.com/ruby/setup-ruby#versioning):
|
36
|
+
# uses: ruby/setup-ruby@v1
|
37
|
+
uses: ruby/setup-ruby@319066216501fbd5e2d568f14b7d68c19fb67a5d # v1.33.1 / 2023-01-06
|
38
|
+
with:
|
39
|
+
ruby-version: ${{ matrix.ruby-version }}
|
40
|
+
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
|
41
|
+
|
42
|
+
- name: Run tests
|
43
|
+
run: bundle exec rake test
|
44
|
+
|
45
|
+
- name: Sorbet Typecheck
|
46
|
+
run: bundle exec srb tc
|
data/.rubocop-disables.yml
CHANGED
@@ -1,7 +1,4 @@
|
|
1
1
|
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
2
|
-
Style/StringLiterals:
|
3
|
-
Enabled: false
|
4
|
-
|
5
2
|
Metrics/AbcSize:
|
6
3
|
Max: 50
|
7
4
|
|
@@ -24,6 +21,9 @@ Metrics/MethodLength:
|
|
24
21
|
Metrics/ModuleLength:
|
25
22
|
Enabled: false
|
26
23
|
|
24
|
+
Metrics/ParameterLists:
|
25
|
+
Enabled: false
|
26
|
+
|
27
27
|
# Configuration parameters: Exclude.
|
28
28
|
#
|
29
29
|
# We could re-enable this if it understood that the top level module should
|
@@ -39,6 +39,11 @@ Style/Documentation:
|
|
39
39
|
# Disagree with these style points
|
40
40
|
# ********************************
|
41
41
|
|
42
|
+
Layout/EmptyLineBetweenDefs:
|
43
|
+
Enabled: false
|
44
|
+
Layout/EmptyLineAfterGuardClause:
|
45
|
+
Enabled: false
|
46
|
+
|
42
47
|
Style/DotPosition:
|
43
48
|
Enabled: false
|
44
49
|
Style/DoubleNegation:
|
@@ -60,12 +65,16 @@ Style/IfUnlessModifier:
|
|
60
65
|
Style/WhileUntilModifier:
|
61
66
|
Enabled: false
|
62
67
|
|
68
|
+
# Don't favor wacky unless methods
|
69
|
+
Style/NegatedIf:
|
70
|
+
Enabled: false
|
71
|
+
Style/InverseMethods:
|
72
|
+
Enabled: false
|
73
|
+
|
63
74
|
Style/InfiniteLoop:
|
64
75
|
Enabled: false
|
65
76
|
Style/PercentLiteralDelimiters:
|
66
|
-
|
67
|
-
'%w': '{}'
|
68
|
-
'%W': '{}'
|
77
|
+
Enabled: false
|
69
78
|
Style/RaiseArgs:
|
70
79
|
EnforcedStyle: compact
|
71
80
|
Style/RedundantReturn:
|
@@ -87,14 +96,13 @@ Style/SpaceInsideBlockBraces:
|
|
87
96
|
Style/SpaceInsideHashLiteralBraces:
|
88
97
|
Enabled: false
|
89
98
|
|
90
|
-
# Offense count: 27
|
91
|
-
# Cop supports --auto-correct.
|
92
99
|
# Configuration parameters: EnforcedStyleForMultiline, SupportedStyles.
|
93
|
-
Style/
|
94
|
-
# SupportedStyles:
|
95
|
-
# - comma
|
96
|
-
# - no_comma
|
100
|
+
Style/TrailingCommaInArrayLiteral:
|
97
101
|
EnforcedStyleForMultiline: comma
|
102
|
+
Style/TrailingCommaInHashLiteral:
|
103
|
+
EnforcedStyleForMultiline: comma
|
104
|
+
Style/TrailingCommaInArguments:
|
105
|
+
Enabled: false
|
98
106
|
|
99
107
|
# Don't favor %w for arrays of words.
|
100
108
|
Style/WordArray:
|
@@ -104,6 +112,9 @@ Style/WordArray:
|
|
104
112
|
Style/SymbolArray:
|
105
113
|
Enabled: false
|
106
114
|
|
115
|
+
Style/NumericLiteralPrefix:
|
116
|
+
Enabled: false
|
117
|
+
|
107
118
|
# Definitely do NOT assign variables within a conditional. Christ.
|
108
119
|
Style/ConditionalAssignment:
|
109
120
|
Enabled: false
|
@@ -131,3 +142,6 @@ Style/GlobalVars:
|
|
131
142
|
Style/SpecialGlobalVars:
|
132
143
|
Exclude:
|
133
144
|
- 'paperback.gemspec'
|
145
|
+
|
146
|
+
Naming/HeredocDelimiterNaming:
|
147
|
+
Enabled: false
|
data/CHANGELOG.md
CHANGED
@@ -4,4 +4,25 @@ This project adheres to [Semantic Versioning](http://semver.org).
|
|
4
4
|
|
5
5
|
## [Unreleased]
|
6
6
|
|
7
|
+
## [0.0.5] -- 2023-01-17
|
8
|
+
|
9
|
+
- Upgrade to modern versions of ruby
|
10
|
+
- Upgrade a few dependencies, fix type checking
|
11
|
+
- Fix tests to work on newer versions of pdftotext
|
12
|
+
- Run tests on Github Actions
|
13
|
+
|
14
|
+
## [0.0.4] -- 2019-02-26
|
15
|
+
|
16
|
+
- Add some basic end-to-end tests.
|
17
|
+
- Add additional copy using base64 encoding, by default.
|
18
|
+
- Add samples and more README notes.
|
19
|
+
|
20
|
+
## [0.0.3] -- 2018-08-15
|
21
|
+
|
22
|
+
- Add option to change sixword font size.
|
23
|
+
|
24
|
+
## [0.0.2] -- 2018-08-14
|
25
|
+
|
26
|
+
- Initial public release
|
27
|
+
|
7
28
|
<!-- vim: set tw=79 : -->
|
data/README.md
CHANGED
@@ -1,30 +1,51 @@
|
|
1
|
-
# Paperback
|
1
|
+
# Paperback
|
2
2
|
|
3
3
|
[](https://rubygems.org/gems/paperback)
|
4
|
-
[](https://travis-ci.org/ab/paperback)
|
5
|
-
[](https://codeclimate.com/github/ab/paperback)
|
6
4
|
[](http://www.rubydoc.info/github/ab/paperback/master)
|
5
|
+
[](https://github.com/ab/paperback/actions/workflows/tests.yml)
|
7
6
|
|
8
7
|
*Paperback* is a library that facilitates the creation of paper offline backups
|
9
8
|
of small amounts of important data, such as encryption keys.
|
10
9
|
|
11
10
|
It is designed to be used for long-term paper storage. Arbitrary data to be
|
12
|
-
backed up is encoded
|
13
|
-
[sixword](https://github.com/ab/sixword) English text.
|
11
|
+
backed up is encoded using QR codes,
|
12
|
+
[sixword](https://github.com/ab/sixword) English text, and Base64.
|
13
|
+
|
14
|
+
Nothing else approaches the durability and inexpensiveness of paper. This
|
15
|
+
library is designed to facilitate the restoration process, which would be
|
16
|
+
tedious and error-prone when using human typists or even OCR.
|
17
|
+
|
18
|
+
The QR code is easily machine readible, the sixword text is easiest to
|
19
|
+
transcribe for humans, and the Base64 serves as a fallback for broadest
|
20
|
+
compatibility.
|
14
21
|
|
15
22
|
By default, the backup data is GPG-encrypted with a symmetric passphrase to
|
16
23
|
avoid exposing data to the printer (or scanner, assuming you cover the
|
17
24
|
passphrase when scanning).
|
18
25
|
|
26
|
+
The printed document does contain the SHA256 digest of the original content for
|
27
|
+
error correction, which is not a problem for random data like keys. But if you
|
28
|
+
are backing up low-entropy secrets and want to preserve the printer-blindness
|
29
|
+
property, pad the content with a random salt or encrypt it before using
|
30
|
+
paperback.
|
31
|
+
|
19
32
|
## Usage
|
20
33
|
|
21
|
-
Typical usage will be through the `paperback` executable.
|
34
|
+
Typical usage will be through the `paperback` executable. Use the `--help`
|
35
|
+
option for a usage menu.
|
22
36
|
|
23
37
|
```sh
|
24
38
|
# Back up the content in data.key
|
25
39
|
paperback data.key out.pdf
|
26
40
|
```
|
27
41
|
|
42
|
+
### Sample output
|
43
|
+
|
44
|
+
See [sample directory](./sample)
|
45
|
+
|
46
|
+

|
47
|
+

|
48
|
+
|
28
49
|
### More complex patterns
|
29
50
|
|
30
51
|
See the [YARD documentation](http://www.rubydoc.info/github/ab/paperback/master).
|
data/bin/paperback
CHANGED
@@ -53,6 +53,10 @@ Options:
|
|
53
53
|
options[:encrypt] = val
|
54
54
|
end
|
55
55
|
|
56
|
+
opts.on('--no-base64', "Don't append plain Base64 paragraph") do |val|
|
57
|
+
options[:include_base64] = val
|
58
|
+
end
|
59
|
+
|
56
60
|
opts.on('--passphrase-out FILE', 'Write generated passphrase to FILE',
|
57
61
|
' ') do |val|
|
58
62
|
options[:passphrase_file] = val
|
data/lib/paperback/cli.rb
CHANGED
@@ -1,12 +1,48 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
1
4
|
module Paperback
|
2
5
|
module CLI
|
6
|
+
extend T::Sig
|
7
|
+
|
8
|
+
# Top level CLI interface for Paperback. This is the one stop shop for
|
9
|
+
# calling paperback.
|
10
|
+
#
|
11
|
+
# @param [String] input The input filename
|
12
|
+
# @param [String] output The output PDF filename
|
13
|
+
# @param [Boolean] encrypt Whether to encrypt input with GPG.
|
14
|
+
# @param [Boolean] qr_base64 Whether to base64 the data before encoding it
|
15
|
+
# as a QR code
|
16
|
+
# @param [Symbol] qr_level Which level of QR code encoding, default `:l`
|
17
|
+
# @param [String,nil] comment A comment to add to the printout
|
18
|
+
# @param [String] passphrase_file A file to write the generated GPG
|
19
|
+
# passphrase to
|
20
|
+
# @param [Hash] extra_draw_opts Other options passed to
|
21
|
+
# [Paperback::Preparer#render]
|
22
|
+
# @param [Boolean] include_base64 Whether to include a Base64 copy of the
|
23
|
+
# input
|
24
|
+
sig do
|
25
|
+
params(
|
26
|
+
input: String,
|
27
|
+
output: String,
|
28
|
+
encrypt: T::Boolean,
|
29
|
+
qr_base64: T::Boolean,
|
30
|
+
qr_level: Symbol,
|
31
|
+
comment: T.nilable(String),
|
32
|
+
passphrase_file: T.nilable(String),
|
33
|
+
extra_draw_opts: T::Hash[T.untyped, T.untyped],
|
34
|
+
include_base64: T::Boolean,
|
35
|
+
)
|
36
|
+
.void
|
37
|
+
end
|
3
38
|
def self.create_backup(input:, output:, encrypt: true, qr_base64: true,
|
4
39
|
qr_level: :l, comment: nil, passphrase_file: nil,
|
5
|
-
extra_draw_opts: {})
|
40
|
+
extra_draw_opts: {}, include_base64: true)
|
6
41
|
prep = Paperback::Preparer.new(filename: input, encrypt: encrypt,
|
7
42
|
qr_base64: qr_base64, qr_level: qr_level,
|
8
43
|
passphrase_file: passphrase_file,
|
9
|
-
comment: comment
|
44
|
+
comment: comment,
|
45
|
+
include_base64: include_base64)
|
10
46
|
prep.render(output_filename: output, extra_draw_opts: extra_draw_opts)
|
11
47
|
end
|
12
48
|
end
|
data/lib/paperback/document.rb
CHANGED
@@ -1,24 +1,43 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
1
4
|
require 'prawn'
|
2
5
|
|
3
6
|
# Main class for creating and rendering PDFs
|
4
7
|
module Paperback; class Document
|
5
|
-
|
8
|
+
extend T::Sig
|
9
|
+
|
10
|
+
sig {returns(Prawn::Document)}
|
11
|
+
attr_reader :pdf
|
6
12
|
|
13
|
+
sig {returns(T::Boolean)}
|
14
|
+
attr_reader :debug
|
15
|
+
|
16
|
+
sig {params(debug: T::Boolean).void}
|
7
17
|
def initialize(debug: false)
|
8
18
|
log.debug('Document#initialize')
|
9
|
-
@debug = debug
|
10
|
-
@pdf = Prawn::Document.new
|
19
|
+
@debug = T.let(debug, T::Boolean)
|
20
|
+
@pdf = T.let(Prawn::Document.new, Prawn::Document)
|
21
|
+
@log = T.let(nil, T.nilable(Logger))
|
11
22
|
end
|
12
23
|
|
24
|
+
sig {returns(Logger)}
|
13
25
|
def log
|
14
26
|
@log ||= Paperback.class_log(self.class)
|
15
27
|
end
|
16
28
|
|
29
|
+
sig do
|
30
|
+
params(
|
31
|
+
output_file: String,
|
32
|
+
draw_opts: T::Hash[Symbol, T.untyped],
|
33
|
+
)
|
34
|
+
.void
|
35
|
+
end
|
17
36
|
def render(output_file:, draw_opts:)
|
18
37
|
log.info('Rendering PDF')
|
19
38
|
|
20
39
|
# Create all the PDF content
|
21
|
-
draw_paperback(**draw_opts)
|
40
|
+
draw_paperback(**T.unsafe(draw_opts))
|
22
41
|
|
23
42
|
# Render to output file
|
24
43
|
log.info("Writing PDF to #{output_file.inspect}")
|
@@ -26,12 +45,39 @@ module Paperback; class Document
|
|
26
45
|
end
|
27
46
|
|
28
47
|
# High level method to draw the paperback content on the pdf document
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
48
|
+
#
|
49
|
+
# @param qr_code
|
50
|
+
# @param sixword_lines
|
51
|
+
# @param sixword_bytes
|
52
|
+
# @param labels
|
53
|
+
# @param passphrase_sha
|
54
|
+
# @param [Integer, nil] passphrase_len Length of the passphrase used to
|
55
|
+
# encrypt the original content. If this is not provided, then assume the
|
56
|
+
# original content was not encrypted and skip adding gpg -d instructions.
|
57
|
+
# @param [Integer] sixword_font_size The font size to use for Sixword text
|
58
|
+
# @param [String,nil] base64_content If provided, then append the original
|
59
|
+
# content (possibly encrypted) encoded using Base64.
|
60
|
+
# @param [Integer, nil] base64_bytes The length of the original content
|
61
|
+
# before encoding to base64. This is used for the informational header.
|
62
|
+
sig do
|
63
|
+
params(
|
64
|
+
qr_code: RQRCode::QRCode,
|
65
|
+
sixword_lines: T::Array[String],
|
66
|
+
sixword_bytes: Integer,
|
67
|
+
labels: T::Hash[String, T.untyped],
|
68
|
+
passphrase_sha: T.nilable(String),
|
69
|
+
passphrase_len: T.nilable(Integer),
|
70
|
+
sixword_font_size: T.nilable(Float),
|
71
|
+
base64_content: T.nilable(String),
|
72
|
+
base64_bytes: T.nilable(Integer),
|
73
|
+
)
|
74
|
+
.void
|
75
|
+
end
|
76
|
+
def draw_paperback(qr_code:, sixword_lines:, sixword_bytes:, labels:,
|
77
|
+
passphrase_sha: nil, passphrase_len: nil,
|
78
|
+
sixword_font_size: nil, base64_content: nil,
|
79
|
+
base64_bytes: nil)
|
80
|
+
T.assert_type!(qr_code, RQRCode::QRCode)
|
35
81
|
|
36
82
|
# Header & QR code page
|
37
83
|
pdf.font('Times-Roman')
|
@@ -53,23 +99,40 @@ module Paperback; class Document
|
|
53
99
|
pdf.start_new_page
|
54
100
|
|
55
101
|
draw_sixword(lines: sixword_lines, sixword_bytes: sixword_bytes,
|
56
|
-
font_size: sixword_font_size
|
102
|
+
font_size: sixword_font_size,
|
103
|
+
is_encrypted: !!passphrase_len)
|
104
|
+
|
105
|
+
if base64_content
|
106
|
+
draw_base64(b64_content: base64_content, b64_bytes: T.must(base64_bytes),
|
107
|
+
is_encrypted: !!passphrase_len)
|
108
|
+
end
|
57
109
|
|
58
110
|
pdf.number_pages('<page> of <total>', align: :right,
|
59
111
|
at: [pdf.bounds.right - 100, -2])
|
60
112
|
end
|
61
113
|
|
62
114
|
# If in debug mode, draw axes on the page to assist with layout
|
115
|
+
sig {void}
|
63
116
|
def debug_draw_axes
|
64
117
|
return unless debug
|
65
118
|
pdf.float { pdf.stroke_axis }
|
66
119
|
end
|
67
120
|
|
68
121
|
# Move cursor down by one line
|
122
|
+
sig {void}
|
69
123
|
def add_newline
|
70
124
|
pdf.move_down(pdf.font_size)
|
71
125
|
end
|
72
126
|
|
127
|
+
sig do
|
128
|
+
params(
|
129
|
+
labels: T::Hash[String, T.untyped],
|
130
|
+
passphrase_sha: T.nilable(String),
|
131
|
+
passphrase_len: T.nilable(Integer),
|
132
|
+
repo_url: String,
|
133
|
+
)
|
134
|
+
.void
|
135
|
+
end
|
73
136
|
def draw_header(labels:, passphrase_sha:, passphrase_len:,
|
74
137
|
repo_url: 'https://github.com/ab/paperback')
|
75
138
|
|
@@ -80,7 +143,7 @@ module Paperback; class Document
|
|
80
143
|
pdf.text(intro, inline_format: true)
|
81
144
|
add_newline
|
82
145
|
|
83
|
-
label_pad = labels.keys.map(&:length).max + 1
|
146
|
+
label_pad = T.must(labels.keys.map(&:length).max) + 1
|
84
147
|
|
85
148
|
unless passphrase_sha && passphrase_len
|
86
149
|
labels['Encrypted'] = 'no'
|
@@ -107,7 +170,8 @@ module Paperback; class Document
|
|
107
170
|
|
108
171
|
pdf.move_down(8)
|
109
172
|
pdf.indent(72) do
|
110
|
-
pdf.text('Be sure to cover the passphrase when scanning the QR code!'
|
173
|
+
pdf.text('Be sure to cover the passphrase when scanning the QR code!' +
|
174
|
+
' Decrypt with `gpg -d`.')
|
111
175
|
end
|
112
176
|
end
|
113
177
|
end
|
@@ -116,8 +180,18 @@ module Paperback; class Document
|
|
116
180
|
# @param [Integer] columns The number of text columns on the page
|
117
181
|
# @param [Integer] hunks_per_row The number of 6-word sentences per line
|
118
182
|
# @param [Integer] sixword_bytes Bytesize of the sixword encoded data
|
183
|
+
sig do
|
184
|
+
params(
|
185
|
+
lines: T::Array[String],
|
186
|
+
sixword_bytes: Integer,
|
187
|
+
columns: Integer,
|
188
|
+
hunks_per_row: Integer,
|
189
|
+
font_size: T.nilable(Float),
|
190
|
+
is_encrypted: T::Boolean,
|
191
|
+
).void
|
192
|
+
end
|
119
193
|
def draw_sixword(lines:, sixword_bytes:, columns: 3, hunks_per_row: 1,
|
120
|
-
font_size: nil)
|
194
|
+
font_size: nil, is_encrypted: true)
|
121
195
|
font_size ||= 11
|
122
196
|
|
123
197
|
debug_draw_axes
|
@@ -128,8 +202,9 @@ module Paperback; class Document
|
|
128
202
|
|
129
203
|
header = [
|
130
204
|
"This sixword text encodes #{sixword_bytes} bytes in #{lines.length}",
|
131
|
-
|
132
|
-
|
205
|
+
' six-word sentences.',
|
206
|
+
' Decode with `sixword -d`',
|
207
|
+
(is_encrypted ? ', then `gpg -d`.' : '.')
|
133
208
|
].join
|
134
209
|
|
135
210
|
pdf.font('Times-Roman') do
|
@@ -146,6 +221,11 @@ module Paperback; class Document
|
|
146
221
|
end
|
147
222
|
end
|
148
223
|
|
224
|
+
sig do
|
225
|
+
params(
|
226
|
+
qr_modules: T::Array[T::Array[T::Boolean]],
|
227
|
+
).void
|
228
|
+
end
|
149
229
|
def draw_qr_code(qr_modules:)
|
150
230
|
qr_height = pdf.cursor # entire rest of page
|
151
231
|
qr_width = pdf.bounds.width # entire page width
|
@@ -170,10 +250,47 @@ module Paperback; class Document
|
|
170
250
|
pdf.stroke_color(pixel_val ? '000000' : 'ffffff')
|
171
251
|
pdf.fill_color(pixel_val ? '000000' : 'ffffff')
|
172
252
|
xy = [(col_i + 1) * pixel_width, pdf.cursor]
|
173
|
-
pdf.
|
253
|
+
pdf.fill_rectangle(xy, pixel_width, pixel_height)
|
174
254
|
end
|
175
255
|
end
|
176
256
|
end
|
177
257
|
end
|
178
258
|
end
|
259
|
+
|
260
|
+
# @param [String] b64_content
|
261
|
+
sig do
|
262
|
+
params(
|
263
|
+
b64_content: String,
|
264
|
+
b64_bytes: Integer,
|
265
|
+
font_size: T.nilable(Float),
|
266
|
+
is_encrypted: T::Boolean,
|
267
|
+
).void
|
268
|
+
end
|
269
|
+
def draw_base64(b64_content:, b64_bytes:, font_size: nil, is_encrypted: true)
|
270
|
+
font_size ||= 11
|
271
|
+
|
272
|
+
debug_draw_axes
|
273
|
+
|
274
|
+
if is_encrypted
|
275
|
+
header = [
|
276
|
+
"This PGP text encodes #{b64_bytes} bytes in #{b64_content.length}",
|
277
|
+
" characters. Decode with `gpg -d`."
|
278
|
+
].join
|
279
|
+
else
|
280
|
+
header = [
|
281
|
+
"This base64 text encodes #{b64_bytes} bytes in #{b64_content.length}",
|
282
|
+
" characters. Decode with `base64 --decode`."
|
283
|
+
].join
|
284
|
+
end
|
285
|
+
|
286
|
+
add_newline
|
287
|
+
add_newline
|
288
|
+
pdf.text(header)
|
289
|
+
add_newline
|
290
|
+
|
291
|
+
pdf.font('Courier') do
|
292
|
+
pdf.text(b64_content)
|
293
|
+
end
|
294
|
+
|
295
|
+
end
|
179
296
|
end; end
|