redactor 0.1.0 → 0.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/.travis.yml +5 -0
- data/README.md +18 -10
- data/lib/redactor/dsl.rb +10 -4
- data/lib/redactor/extract.rb +1 -1
- data/lib/redactor/rule.rb +1 -1
- data/lib/redactor/version.rb +2 -2
- data/lib/redactor.rb +13 -17
- data/spec/lib/{dsl_spec.rb → redactor/dsl_spec.rb} +10 -4
- data/spec/lib/{rules_spec.rb → redactor/rules_spec.rb} +5 -7
- data/spec/lib/redactor_spec.rb +81 -0
- metadata +15 -16
- data/lib/redactor/clear.rb +0 -5
- data/spec/lib/clear_spec.rb +0 -11
- data/spec/lib/redact_spec.rb +0 -55
- /data/spec/lib/{extract_spec.rb → redactor/extract_spec.rb} +0 -0
- /data/spec/lib/{rule_spec.rb → redactor/rule_spec.rb} +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7a2cd8062ddf0427c5f9e0658c10ca0648773eb4
|
4
|
+
data.tar.gz: b991cd754a805b19ad6db954537b0c41ff91a5fc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cc6e7d25df877a0d796b42b43687c84a9da5213233e72fe8380b1a61a7ad8a192f3c81045f4d4c49dab75e83b1e48397238d9562fe8b7394f66157f51e1701ec
|
7
|
+
data.tar.gz: 6a805cb5eeb3470149f2e44bcb7d31d495ecfd7822d7e074918f11d2dc5f10050bcbc21d793bd179b7716ebbeaec8f8a82d6032649d599876316b2974fdc21cf
|
data/.travis.yml
ADDED
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# redactor
|
1
|
+
# redactor [](https://rubygems.org/gems/redactor) [](https://travis-ci.org/TimPetricola/redactor)
|
2
2
|
|
3
3
|
Redact parts of text defined by custom rules (e.g. emails, phone numbers).
|
4
4
|
|
@@ -10,7 +10,7 @@ require 'redactor'
|
|
10
10
|
input = 'To ride a kayak, contact me: tim.petricola@gmail.com or 1 234 567 8901.'
|
11
11
|
|
12
12
|
# these rules are only good enough for an example
|
13
|
-
Redactor.
|
13
|
+
@redactor = Redactor.new do
|
14
14
|
# US phone
|
15
15
|
rule :phone, /(\+?1[ \.-]?)?\(?\d{3}\)?[ \.-]?\d{3}[ \.-]?\d{4}/
|
16
16
|
|
@@ -29,24 +29,32 @@ Redactor.define do
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
-
|
32
|
+
redactor.format(input)
|
33
33
|
# => "To ride a [REDACTED], contact me: [REDACTED] or [REDACTED]."
|
34
34
|
|
35
|
-
|
35
|
+
redactor.default_replacement = '$#@!&'
|
36
|
+
# => "To ride a $\#@!&, contact me: $\#@!& or $\#@!&."
|
37
|
+
|
38
|
+
redactor.format(input) do |extract|
|
36
39
|
"[#{extract.reason.upcase}]"
|
37
40
|
end
|
38
41
|
# => "To ride a [PALINDROME], contact me: [EMAIL] or [PHONE]."
|
39
42
|
|
40
|
-
|
41
|
-
# => [#<Redactor::Extract:
|
43
|
+
redactor.extract(input)
|
44
|
+
# => [#<Redactor::Extract:0x007ff259586008
|
42
45
|
# @finish=70,
|
43
|
-
# @rule=#<Redactor::Rule:
|
46
|
+
# @rule=#<Redactor::Rule:0x007ff258b5aa20 @block=nil, @reason=:phone, @regex=/(\+?1[ \.-]?)?\(?\d{3}\)?[ \.-]?\d{3}[ \.-]?\d{4}/>,
|
44
47
|
# @start=56,
|
45
48
|
# @value="1 234 567 8901">,
|
46
|
-
# #<Redactor::Extract:
|
47
|
-
#
|
49
|
+
# #<Redactor::Extract:0x007ff259585cc0
|
50
|
+
# @finish=52,
|
51
|
+
# @rule=#<Redactor::Rule:0x007ff258b5a9f8 @block=nil, @reason=:email, @regex=/[\w\.]+(@|at)\w+(\.|dot)\w{1,3}/i>,
|
52
|
+
# @start=29,
|
53
|
+
# @value="tim.petricola@gmail.com">,
|
54
|
+
# #<Redactor::Extract:0x007ff259585518
|
48
55
|
# @finish=15,
|
49
|
-
# @rule=#<Redactor::Rule:
|
56
|
+
# @rule=#<Redactor::Rule:0x007ff258b5a980 @block=#<Proc:0x007ff258b5a9a8@/Users/Tim/Projects/redactor/test.rb:14>, @reason=:palindrome, @regex=nil>,
|
50
57
|
# @start=10,
|
51
58
|
# @value="kayak">]
|
59
|
+
|
52
60
|
```
|
data/lib/redactor/dsl.rb
CHANGED
@@ -1,12 +1,18 @@
|
|
1
|
-
|
1
|
+
class Redactor
|
2
2
|
class DSL
|
3
|
+
attr_reader :redactor
|
4
|
+
|
5
|
+
def initialize(redactor)
|
6
|
+
@redactor = redactor
|
7
|
+
end
|
8
|
+
|
3
9
|
def rule(reason, regex = nil, &block)
|
4
10
|
rule = Rule.new(reason, regex, &block)
|
5
|
-
|
11
|
+
redactor.register_rule(rule)
|
6
12
|
end
|
7
13
|
|
8
|
-
def self.run(block)
|
9
|
-
new.instance_eval(&block)
|
14
|
+
def self.run(redactor, block)
|
15
|
+
new(redactor).instance_eval(&block)
|
10
16
|
end
|
11
17
|
end
|
12
18
|
end
|
data/lib/redactor/extract.rb
CHANGED
data/lib/redactor/rule.rb
CHANGED
data/lib/redactor/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
|
2
|
-
VERSION = '0.
|
1
|
+
class Redactor
|
2
|
+
VERSION = '0.2.0'
|
3
3
|
end
|
data/lib/redactor.rb
CHANGED
@@ -1,30 +1,22 @@
|
|
1
|
-
|
2
|
-
require 'redactor/dsl'
|
3
|
-
require 'redactor/extract'
|
4
|
-
require 'redactor/rule'
|
5
|
-
|
6
|
-
module Redactor
|
1
|
+
class Redactor
|
7
2
|
DEFAULT_REPLACEMENT = '[REDACTED]'.freeze
|
8
3
|
|
9
|
-
|
10
|
-
attr_accessor :rules
|
11
|
-
attr_accessor :default_replacement
|
12
|
-
end
|
4
|
+
attr_accessor :rules, :default_replacement
|
13
5
|
|
14
|
-
|
15
|
-
|
6
|
+
def initialize(rules = [], &block)
|
7
|
+
@default_replacement = DEFAULT_REPLACEMENT
|
8
|
+
@rules = Array(rules)
|
16
9
|
|
17
|
-
|
18
|
-
DSL.run(block)
|
10
|
+
DSL.run(self, block) if block_given?
|
19
11
|
end
|
20
12
|
|
21
|
-
def
|
13
|
+
def register_rule(rule)
|
22
14
|
rules.push(rule)
|
23
15
|
end
|
24
16
|
|
25
17
|
# returns a list of Extract objects (including position and value)
|
26
18
|
# matching predefined rules
|
27
|
-
def
|
19
|
+
def extract(from)
|
28
20
|
rules.reduce([]) do |extracts, rule|
|
29
21
|
new_extracts = rule.extract(from).select do |extract|
|
30
22
|
# do not consider new extract if colliding with existing one
|
@@ -36,10 +28,14 @@ module Redactor
|
|
36
28
|
|
37
29
|
# replaces parts of text by [REDACTED]. The replacement string can be
|
38
30
|
# customized by passing a block taking the Extract object as an argument
|
39
|
-
def
|
31
|
+
def format(text, &block)
|
40
32
|
extract(text).each_with_object(text.clone) do |extract, redacted_text|
|
41
33
|
sub = block_given? ? block.call(extract) : default_replacement
|
42
34
|
redacted_text[extract.start...extract.finish] = sub
|
43
35
|
end
|
44
36
|
end
|
45
37
|
end
|
38
|
+
|
39
|
+
require 'redactor/dsl'
|
40
|
+
require 'redactor/extract'
|
41
|
+
require 'redactor/rule'
|
@@ -8,13 +8,16 @@ describe Redactor::DSL do
|
|
8
8
|
rule :foo, /foo/
|
9
9
|
end
|
10
10
|
|
11
|
+
redactor = double
|
11
12
|
rule = double('Redactor::Rule')
|
13
|
+
|
12
14
|
expect(Redactor::Rule).to(
|
13
15
|
receive(:new).with(:foo, /foo/).and_return(rule)
|
14
16
|
)
|
15
|
-
expect(Redactor).to receive(:register_rule).with(rule)
|
16
17
|
|
17
|
-
|
18
|
+
expect(redactor).to receive(:register_rule).with(rule)
|
19
|
+
|
20
|
+
Redactor::DSL.run(redactor, definitions)
|
18
21
|
end
|
19
22
|
end
|
20
23
|
|
@@ -26,16 +29,19 @@ describe Redactor::DSL do
|
|
26
29
|
rule(:foo, &proc)
|
27
30
|
end
|
28
31
|
|
32
|
+
redactor = double
|
29
33
|
rule = double('Redactor::Rule')
|
34
|
+
|
30
35
|
expect(Redactor::Rule).to(
|
31
36
|
receive(:new).with(:foo, nil) do |*_args, &block|
|
32
37
|
expect(proc).to be(block)
|
33
38
|
rule
|
34
39
|
end
|
35
40
|
)
|
36
|
-
expect(Redactor).to receive(:register_rule).with(rule)
|
37
41
|
|
38
|
-
|
42
|
+
expect(redactor).to receive(:register_rule).with(rule)
|
43
|
+
|
44
|
+
Redactor::DSL.run(redactor, definitions)
|
39
45
|
end
|
40
46
|
end
|
41
47
|
end
|
@@ -1,16 +1,16 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
RSpec::Matchers.define :be_redacted do |reason|
|
3
|
+
RSpec::Matchers.define :be_redacted do |reason, redactor|
|
4
4
|
match do |actual|
|
5
|
-
|
5
|
+
redactor.extract(actual).any? do |extract|
|
6
6
|
extract.value == actual && extract.reason == reason
|
7
7
|
end
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
11
|
describe 'Redactor rules' do
|
12
|
-
|
13
|
-
Redactor.
|
12
|
+
let(:redactor) do
|
13
|
+
Redactor.new do
|
14
14
|
# US phone
|
15
15
|
rule :phone, /(\+?1[ \.-]?)?\(?\d{3}\)?[ \.-]?\d{3}[ \.-]?\d{4}/
|
16
16
|
|
@@ -19,8 +19,6 @@ describe 'Redactor rules' do
|
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
-
after { Redactor.clear }
|
23
|
-
|
24
22
|
{
|
25
23
|
'1 234 567 8901' => :phone,
|
26
24
|
'12345678901' => :phone,
|
@@ -36,7 +34,7 @@ describe 'Redactor rules' do
|
|
36
34
|
'foo AT bar DOT baz' => :email
|
37
35
|
}.each do |value, reason|
|
38
36
|
describe(value) do
|
39
|
-
it { should be_redacted(reason) }
|
37
|
+
it { should be_redacted(reason, redactor) }
|
40
38
|
end
|
41
39
|
end
|
42
40
|
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Redactor do
|
4
|
+
let(:foobar_rule) { Redactor::Rule.new(:foobar, /foobar/) }
|
5
|
+
let(:barbaz_rule) { Redactor::Rule.new(:barbaz, /barbaz/) }
|
6
|
+
|
7
|
+
it 'accepts a single rule' do
|
8
|
+
redactor = Redactor.new(foobar_rule)
|
9
|
+
expect(redactor.rules).to eq [foobar_rule]
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'accepts an array of rule' do
|
13
|
+
redactor = Redactor.new([foobar_rule])
|
14
|
+
expect(redactor.rules).to eq [foobar_rule]
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'accepts a block' do
|
18
|
+
redactor = Redactor.new do
|
19
|
+
rule :foo, /foo/
|
20
|
+
end
|
21
|
+
expect(redactor.rules.length).to be 1
|
22
|
+
expect(redactor.rules[0].reason).to eq :foo
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '.extract' do
|
26
|
+
let(:redactor) do
|
27
|
+
redactor = Redactor.new
|
28
|
+
redactor.register_rule(foobar_rule)
|
29
|
+
redactor.register_rule(barbaz_rule)
|
30
|
+
redactor
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'return extracts' do
|
34
|
+
text = 'hello barbaz foobar'
|
35
|
+
results = redactor.extract(text)
|
36
|
+
expect(results.first.rule).to be foobar_rule
|
37
|
+
expect(results.first.value).to eq 'foobar'
|
38
|
+
expect(results.last.rule).to be barbaz_rule
|
39
|
+
expect(results.last.value).to eq 'barbaz'
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'colliding rules' do
|
43
|
+
it "only keep first defined rule's match" do
|
44
|
+
text = 'hello foobarbaz'
|
45
|
+
results = redactor.extract(text)
|
46
|
+
expect(results.size).to eq 1
|
47
|
+
expect(results.first.rule).to be foobar_rule
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe '.format' do
|
53
|
+
let(:redactor) do
|
54
|
+
redactor = Redactor.new
|
55
|
+
redactor.register_rule(foobar_rule)
|
56
|
+
redactor.register_rule(barbaz_rule)
|
57
|
+
redactor
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'replaces redacted parts' do
|
61
|
+
text = 'hello barbaz foobar'
|
62
|
+
expect(redactor.format(text)).to eq 'hello [REDACTED] [REDACTED]'
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'accepts a block for redacted strings' do
|
66
|
+
text = 'hello barbaz foobar'
|
67
|
+
|
68
|
+
redacted = redactor.format(text) do |extract|
|
69
|
+
"[#{extract.reason.upcase}]"
|
70
|
+
end
|
71
|
+
|
72
|
+
expect(redacted).to eq 'hello [BARBAZ] [FOOBAR]'
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'does not mutate original string' do
|
76
|
+
text = 'hello barbaz foobar'
|
77
|
+
redactor.format(text)
|
78
|
+
expect(text).to eq 'hello barbaz foobar'
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redactor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tim Petricola
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-10-
|
11
|
+
date: 2015-10-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -46,24 +46,23 @@ extensions: []
|
|
46
46
|
extra_rdoc_files: []
|
47
47
|
files:
|
48
48
|
- ".gitignore"
|
49
|
+
- ".travis.yml"
|
49
50
|
- Gemfile
|
50
51
|
- Gemfile.lock
|
51
52
|
- LICENSE
|
52
53
|
- README.md
|
53
54
|
- Rakefile
|
54
55
|
- lib/redactor.rb
|
55
|
-
- lib/redactor/clear.rb
|
56
56
|
- lib/redactor/dsl.rb
|
57
57
|
- lib/redactor/extract.rb
|
58
58
|
- lib/redactor/rule.rb
|
59
59
|
- lib/redactor/version.rb
|
60
60
|
- redactor.gemspec
|
61
|
-
- spec/lib/
|
62
|
-
- spec/lib/
|
63
|
-
- spec/lib/
|
64
|
-
- spec/lib/
|
65
|
-
- spec/lib/
|
66
|
-
- spec/lib/rules_spec.rb
|
61
|
+
- spec/lib/redactor/dsl_spec.rb
|
62
|
+
- spec/lib/redactor/extract_spec.rb
|
63
|
+
- spec/lib/redactor/rule_spec.rb
|
64
|
+
- spec/lib/redactor/rules_spec.rb
|
65
|
+
- spec/lib/redactor_spec.rb
|
67
66
|
- spec/spec_helper.rb
|
68
67
|
homepage: https://github.com/TimPetricola/redactor
|
69
68
|
licenses:
|
@@ -85,15 +84,15 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
85
84
|
version: '0'
|
86
85
|
requirements: []
|
87
86
|
rubyforge_project:
|
88
|
-
rubygems_version: 2.2.
|
87
|
+
rubygems_version: 2.2.2
|
89
88
|
signing_key:
|
90
89
|
specification_version: 4
|
91
90
|
summary: Redact parts of text defined by custom rules (e.g. emails, phone numbers)
|
92
91
|
test_files:
|
93
|
-
- spec/lib/
|
94
|
-
- spec/lib/
|
95
|
-
- spec/lib/
|
96
|
-
- spec/lib/
|
97
|
-
- spec/lib/
|
98
|
-
- spec/lib/rules_spec.rb
|
92
|
+
- spec/lib/redactor/dsl_spec.rb
|
93
|
+
- spec/lib/redactor/extract_spec.rb
|
94
|
+
- spec/lib/redactor/rule_spec.rb
|
95
|
+
- spec/lib/redactor/rules_spec.rb
|
96
|
+
- spec/lib/redactor_spec.rb
|
99
97
|
- spec/spec_helper.rb
|
98
|
+
has_rdoc:
|
data/lib/redactor/clear.rb
DELETED
data/spec/lib/clear_spec.rb
DELETED
data/spec/lib/redact_spec.rb
DELETED
@@ -1,55 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Redactor do
|
4
|
-
before do
|
5
|
-
@foobar_rule = Redactor::Rule.new(:foobar, /foobar/)
|
6
|
-
@barbaz_rule = Redactor::Rule.new(:barbaz, /barbaz/)
|
7
|
-
Redactor.register_rule(@foobar_rule)
|
8
|
-
Redactor.register_rule(@barbaz_rule)
|
9
|
-
end
|
10
|
-
|
11
|
-
after { Redactor.clear }
|
12
|
-
|
13
|
-
describe '.extract' do
|
14
|
-
it 'return extracts' do
|
15
|
-
text = 'hello barbaz foobar'
|
16
|
-
results = Redactor.extract(text)
|
17
|
-
expect(results.first.rule).to be @foobar_rule
|
18
|
-
expect(results.first.value).to eq 'foobar'
|
19
|
-
expect(results.last.rule).to be @barbaz_rule
|
20
|
-
expect(results.last.value).to eq 'barbaz'
|
21
|
-
end
|
22
|
-
|
23
|
-
context 'colliding rules' do
|
24
|
-
it "only keep first defined rule's match" do
|
25
|
-
text = 'hello foobarbaz'
|
26
|
-
results = Redactor.extract(text)
|
27
|
-
expect(results.size).to eq 1
|
28
|
-
expect(results.first.rule).to be @foobar_rule
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
describe '.format' do
|
34
|
-
it 'replaces redacted parts' do
|
35
|
-
text = 'hello barbaz foobar'
|
36
|
-
expect(Redactor.format(text)).to eq 'hello [REDACTED] [REDACTED]'
|
37
|
-
end
|
38
|
-
|
39
|
-
it 'accepts a block for redacted strings' do
|
40
|
-
text = 'hello barbaz foobar'
|
41
|
-
|
42
|
-
redacted = Redactor.format(text) do |extract|
|
43
|
-
"[#{extract.reason.upcase}]"
|
44
|
-
end
|
45
|
-
|
46
|
-
expect(redacted).to eq 'hello [BARBAZ] [FOOBAR]'
|
47
|
-
end
|
48
|
-
|
49
|
-
it 'does not mutate original string' do
|
50
|
-
text = 'hello barbaz foobar'
|
51
|
-
Redactor.format(text)
|
52
|
-
expect(text).to eq 'hello barbaz foobar'
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
File without changes
|
File without changes
|