redactor 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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 [![Gem Version](https://badge.fury.io/rb/redactor.svg)](https://rubygems.org/gems/redactor) [![Build Status](https://travis-ci.org/TimPetricola/redactor.svg)](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
|