sanitized 0.7.4
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 +7 -0
- data/lib/sanitized/base.rb +108 -0
- data/lib/sanitized/big_integer.rb +42 -0
- data/lib/sanitized/date_time.rb +119 -0
- data/lib/sanitized/decimal.rb +45 -0
- data/lib/sanitized/float.rb +47 -0
- data/lib/sanitized/integer.rb +43 -0
- data/lib/sanitized/string.rb +63 -0
- data/lib/sanitized.rb +9 -0
- metadata +72 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: dd102b8894c675e59654a16ad09200bcee7ca8e9a410877c8799bf08902d727b
|
4
|
+
data.tar.gz: 3c651c4bac7befac379afc9df19485bbd6acb3b66394a2cfbf8d6c23e49866dc
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 2e4ab716cf16e94b41a88826bb3eeca23797cd847622021704a63d98ab595c50e1118ae28ad38d12062b3714af19ae89862914d3bbce93b47462401ce6414288
|
7
|
+
data.tar.gz: b69aa464d63b0ee835f2cf8a9bd3f8722bbbccb3e5673fc1573c418c090544c1dd0326a6352f9c3c5f67f1d3135a73c8c522c6cd3486e0236e12e9119014b763
|
@@ -0,0 +1,108 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sanitized
|
4
|
+
|
5
|
+
##
|
6
|
+
# Base methods for all Sanitized classes
|
7
|
+
#
|
8
|
+
module Base # :nodoc:
|
9
|
+
|
10
|
+
##
|
11
|
+
# sanitize the value according to the options provided on initialization.
|
12
|
+
#
|
13
|
+
def cast(value) # :nodoc:
|
14
|
+
val = super
|
15
|
+
val = sanitize(val)
|
16
|
+
val = @block.call(val) if @block.present?
|
17
|
+
return val
|
18
|
+
rescue
|
19
|
+
nil
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
|
24
|
+
# public reader for set options
|
25
|
+
def options
|
26
|
+
@options ||= []
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
|
31
|
+
|
32
|
+
|
33
|
+
# ======================================================================
|
34
|
+
# = Private
|
35
|
+
# ======================================================================
|
36
|
+
private
|
37
|
+
|
38
|
+
# Set the options, record the block and verfiy that every given option is valid
|
39
|
+
#
|
40
|
+
# [:opts]
|
41
|
+
# An Array of Symbol options to be run with every :cast
|
42
|
+
#
|
43
|
+
# [:block]
|
44
|
+
# An optional block to be run with every :cast
|
45
|
+
#
|
46
|
+
# attribute :title, Sanitized::String.new(:squish, :titleize) do |value|
|
47
|
+
# value += '.' unless value.ends_with?('.')
|
48
|
+
# end
|
49
|
+
#
|
50
|
+
def initialize(*opts, &block)
|
51
|
+
@options = []
|
52
|
+
@block = block if block_given?
|
53
|
+
|
54
|
+
assert_valid_options(opts)
|
55
|
+
super()
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
|
60
|
+
# raise an exception if any given option is invalid
|
61
|
+
def assert_valid_options(opts)
|
62
|
+
opts.each do |opt|
|
63
|
+
fail_invalid_option(opt) unless valid_options.keys.include?(opt)
|
64
|
+
|
65
|
+
# check for exclusive options
|
66
|
+
if valid_options[opt].present? and options.present?
|
67
|
+
valid_options[opt].each do |exclusive_opt|
|
68
|
+
if options.include?(exclusive_opt)
|
69
|
+
msg = ":#{opt.to_s} and :#{exclusive_opt} are mutually exclusive."\
|
70
|
+
" You may only use one or the other."
|
71
|
+
fail ArgumentError, msg
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
options << opt
|
77
|
+
end # each |opt|
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
|
82
|
+
# raise an error based on the invalid option
|
83
|
+
def fail_invalid_option(opt)
|
84
|
+
if opt.is_a?(Symbol)
|
85
|
+
fail ArgumentError, ":#{opt.to_s} is not a valid option."
|
86
|
+
else
|
87
|
+
fail ArgumentError, "Options must be a Symbol, not #{opt.class.name}."
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
|
92
|
+
|
93
|
+
# return a Hash of valid options with the other options they are exclusive with
|
94
|
+
def valid_options
|
95
|
+
self.class.valid_options
|
96
|
+
end
|
97
|
+
|
98
|
+
|
99
|
+
|
100
|
+
# apply the required sanitization to the vlaue.
|
101
|
+
def sanitize(value) # :nodoc
|
102
|
+
result = value
|
103
|
+
options.each { |opt| result = result.send(opt) }
|
104
|
+
return result
|
105
|
+
end
|
106
|
+
|
107
|
+
end # base
|
108
|
+
end # sanitized
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sanitized
|
4
|
+
|
5
|
+
##
|
6
|
+
# = Description
|
7
|
+
#
|
8
|
+
# ActiveModel::Type to cast and sanitize a model's BigInt attribute according to the
|
9
|
+
# options specified on initialisation.
|
10
|
+
#
|
11
|
+
# attribute :attr_name, Sanitized::BigInt.new(:abs), default: 123
|
12
|
+
#
|
13
|
+
# Can optionally include a custom block:
|
14
|
+
# type_cast = Sanitized::BigInt.new(:abs) do |value|
|
15
|
+
# ... custome code ...
|
16
|
+
# end
|
17
|
+
# attribute :attr_name, type_cast, default: 123
|
18
|
+
#
|
19
|
+
class BigInteger < ::ActiveModel::Type::BigInteger
|
20
|
+
|
21
|
+
# ======================================================================
|
22
|
+
# Macros
|
23
|
+
# ======================================================================
|
24
|
+
|
25
|
+
include Sanitized::Base
|
26
|
+
|
27
|
+
|
28
|
+
|
29
|
+
# ======================================================================
|
30
|
+
# Class Methods
|
31
|
+
# ======================================================================
|
32
|
+
|
33
|
+
##
|
34
|
+
# Returns a Hash of valid options with the other options they are exclusive with
|
35
|
+
#
|
36
|
+
def self.valid_options
|
37
|
+
{
|
38
|
+
abs: []
|
39
|
+
}
|
40
|
+
end
|
41
|
+
end # class Type
|
42
|
+
end # module
|
@@ -0,0 +1,119 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sanitized
|
4
|
+
|
5
|
+
##
|
6
|
+
# = Description
|
7
|
+
#
|
8
|
+
# ActiveModel::Type to cast and sanitize a model's DateTime attribute according to the
|
9
|
+
# options specified on initialisation.
|
10
|
+
#
|
11
|
+
# attribute :attr_name, Sanitized::DateTime.new(:end_of_week, :at_noon), default: Time.now
|
12
|
+
#
|
13
|
+
# Can optionally include a custom block:
|
14
|
+
# type_cast = Sanitized::DateTime.new(:beginning_of_week, :at_noon) do |value|
|
15
|
+
# ... custome code ...
|
16
|
+
# end
|
17
|
+
# attribute :attr_name, type_cast, default: Date.today
|
18
|
+
#
|
19
|
+
class DateTime < ::ActiveModel::Type::DateTime
|
20
|
+
|
21
|
+
# ======================================================================
|
22
|
+
# Macros
|
23
|
+
# ======================================================================
|
24
|
+
|
25
|
+
include Sanitized::Base
|
26
|
+
|
27
|
+
|
28
|
+
|
29
|
+
# ======================================================================
|
30
|
+
# Class Methods
|
31
|
+
# ======================================================================
|
32
|
+
|
33
|
+
# return a Hash of valid options with the other options they are exclusive with
|
34
|
+
def self.valid_options
|
35
|
+
{
|
36
|
+
at_beginning_of_day: self.exclusive_options,
|
37
|
+
at_beginning_of_hour: self.exclusive_options,
|
38
|
+
at_beginning_of_minute: self.exclusive_options,
|
39
|
+
at_beginning_of_month: self.exclusive_options,
|
40
|
+
at_beginning_of_quarter: self.exclusive_options,
|
41
|
+
at_beginning_of_week: self.exclusive_options,
|
42
|
+
at_beginning_of_year: self.exclusive_options,
|
43
|
+
at_end_of_day: self.exclusive_options,
|
44
|
+
at_end_of_hour: self.exclusive_options,
|
45
|
+
at_end_of_minute: self.exclusive_options,
|
46
|
+
at_end_of_month: self.exclusive_options,
|
47
|
+
at_end_of_quarter: self.exclusive_options,
|
48
|
+
at_end_of_week: self.exclusive_options,
|
49
|
+
at_end_of_year: self.exclusive_options,
|
50
|
+
at_midday: self.exclusive_options,
|
51
|
+
at_middle_of_day: self.exclusive_options,
|
52
|
+
at_midnight: self.exclusive_options,
|
53
|
+
at_noon: self.exclusive_options,
|
54
|
+
beginning_of_day: self.exclusive_options,
|
55
|
+
beginning_of_hour: self.exclusive_options,
|
56
|
+
beginning_of_minute: self.exclusive_options,
|
57
|
+
beginning_of_month: self.exclusive_options,
|
58
|
+
beginning_of_quarter: self.exclusive_options,
|
59
|
+
beginning_of_week: self.exclusive_options,
|
60
|
+
beginning_of_year: self.exclusive_options,
|
61
|
+
end_of_month: self.exclusive_options,
|
62
|
+
end_of_quarter: self.exclusive_options,
|
63
|
+
end_of_week: self.exclusive_options,
|
64
|
+
end_of_year: self.exclusive_options,
|
65
|
+
end_of_day: self.exclusive_options,
|
66
|
+
end_of_hour: self.exclusive_options,
|
67
|
+
end_of_minute: self.exclusive_options,
|
68
|
+
midday: self.exclusive_options,
|
69
|
+
middle_of_day: self.exclusive_options,
|
70
|
+
midnight: self.exclusive_options,
|
71
|
+
noon: self.exclusive_options
|
72
|
+
}
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
|
77
|
+
# Return an Array of the options that modify both the date and the time
|
78
|
+
def self.exclusive_options
|
79
|
+
[
|
80
|
+
:at_beginning_of_day,
|
81
|
+
:at_beginning_of_hour,
|
82
|
+
:at_beginning_of_minute,
|
83
|
+
:at_beginning_of_month,
|
84
|
+
:at_beginning_of_quarter,
|
85
|
+
:at_beginning_of_week,
|
86
|
+
:at_beginning_of_year,
|
87
|
+
:at_end_of_day,
|
88
|
+
:at_end_of_hour,
|
89
|
+
:at_end_of_minute,
|
90
|
+
:at_end_of_month,
|
91
|
+
:at_end_of_quarter,
|
92
|
+
:at_end_of_week,
|
93
|
+
:at_end_of_year,
|
94
|
+
:at_midday,
|
95
|
+
:at_middle_of_day,
|
96
|
+
:at_midnight,
|
97
|
+
:at_noon,
|
98
|
+
:beginning_of_day,
|
99
|
+
:beginning_of_hour,
|
100
|
+
:beginning_of_minute,
|
101
|
+
:beginning_of_month,
|
102
|
+
:beginning_of_quarter,
|
103
|
+
:beginning_of_week,
|
104
|
+
:beginning_of_year,
|
105
|
+
:end_of_month,
|
106
|
+
:end_of_quarter,
|
107
|
+
:end_of_week,
|
108
|
+
:end_of_year,
|
109
|
+
:end_of_day,
|
110
|
+
:end_of_hour,
|
111
|
+
:end_of_minute,
|
112
|
+
:midday,
|
113
|
+
:middle_of_day,
|
114
|
+
:midnight,
|
115
|
+
:noon
|
116
|
+
]
|
117
|
+
end
|
118
|
+
end # class Type
|
119
|
+
end # module
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sanitized
|
4
|
+
|
5
|
+
##
|
6
|
+
# = Description
|
7
|
+
#
|
8
|
+
# ActiveModel::Type to cast and sanitize a model's Decimal attribute according to the
|
9
|
+
# options specified on initialisation.
|
10
|
+
#
|
11
|
+
# attribute :attr_name, Sanitized::Decimal.new(:abs, :ceil), default: 123.45
|
12
|
+
#
|
13
|
+
# Can optionally include a custom block:
|
14
|
+
# type_cast = Sanitized::Decimal.new(:abs, :ceil) do |value|
|
15
|
+
# ... custome code ...
|
16
|
+
# end
|
17
|
+
# attribute :attr_name, type_cast, default: 123.45
|
18
|
+
#
|
19
|
+
class Decimal < ::ActiveModel::Type::Decimal
|
20
|
+
|
21
|
+
# ======================================================================
|
22
|
+
# Macros
|
23
|
+
# ======================================================================
|
24
|
+
|
25
|
+
include Sanitized::Base
|
26
|
+
|
27
|
+
|
28
|
+
|
29
|
+
# ======================================================================
|
30
|
+
# Class Methods
|
31
|
+
# ======================================================================
|
32
|
+
|
33
|
+
##
|
34
|
+
# Returns a Hash of valid options with the other options they are exclusive with
|
35
|
+
#
|
36
|
+
def self.valid_options
|
37
|
+
{
|
38
|
+
abs: [],
|
39
|
+
ceil: [:floor],
|
40
|
+
floor: [:ceil],
|
41
|
+
truncate: []
|
42
|
+
}
|
43
|
+
end
|
44
|
+
end # class Type
|
45
|
+
end # module
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sanitized
|
4
|
+
|
5
|
+
##
|
6
|
+
# = Description
|
7
|
+
#
|
8
|
+
# ActiveModel::Type to cast and sanitize a model's Float attribute according to the
|
9
|
+
# options specified on initialisation.
|
10
|
+
#
|
11
|
+
# attribute :attr_name, Sanitized::Float.new(:abs, :ceil), default: 123.45
|
12
|
+
#
|
13
|
+
# Can optionally include a custom block:
|
14
|
+
# type_cast = Sanitized::Float.new(:abs, :ceil) do |value|
|
15
|
+
# ... custome code ...
|
16
|
+
# end
|
17
|
+
# attribute :attr_name, type_cast, default: 123.45
|
18
|
+
#
|
19
|
+
class Float < ::ActiveModel::Type::Float
|
20
|
+
|
21
|
+
# ======================================================================
|
22
|
+
# Macros
|
23
|
+
# ======================================================================
|
24
|
+
|
25
|
+
include Sanitized::Base
|
26
|
+
|
27
|
+
|
28
|
+
|
29
|
+
# ======================================================================
|
30
|
+
# Class Methods
|
31
|
+
# ======================================================================
|
32
|
+
|
33
|
+
##
|
34
|
+
# Returns a Hash of valid options with the other options they are exclusive with
|
35
|
+
#
|
36
|
+
def self.valid_options
|
37
|
+
{
|
38
|
+
abs: [:magnitude],
|
39
|
+
ceil: [:floor],
|
40
|
+
floor: [:ceil],
|
41
|
+
magnitude: [:abs],
|
42
|
+
truncate: [],
|
43
|
+
}
|
44
|
+
end
|
45
|
+
|
46
|
+
end # class Type
|
47
|
+
end # module
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sanitized
|
4
|
+
|
5
|
+
##
|
6
|
+
# = Description
|
7
|
+
#
|
8
|
+
# ActiveModel::Type to cast and sanitize a model's Integer attribute according to the
|
9
|
+
# options specified on initialisation.
|
10
|
+
#
|
11
|
+
# attribute :attr_name, Sanitized::Integer.new(:abs), default: 123
|
12
|
+
#
|
13
|
+
# Can optionally include a custom block:
|
14
|
+
# type_cast = Sanitized::Integer.new(:abs) do |value|
|
15
|
+
# ... custome code ...
|
16
|
+
# end
|
17
|
+
# attribute :attr_name, type_cast, default: 123
|
18
|
+
#
|
19
|
+
class Integer < ::ActiveModel::Type::Integer
|
20
|
+
|
21
|
+
# ======================================================================
|
22
|
+
# Macros
|
23
|
+
# ======================================================================
|
24
|
+
|
25
|
+
include Sanitized::Base
|
26
|
+
|
27
|
+
|
28
|
+
|
29
|
+
# ======================================================================
|
30
|
+
# Class Methods
|
31
|
+
# ======================================================================
|
32
|
+
|
33
|
+
##
|
34
|
+
# Returns a Hash of valid options with the other options they are exclusive with
|
35
|
+
#
|
36
|
+
def self.valid_options
|
37
|
+
{
|
38
|
+
abs: []
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
end # class Type
|
43
|
+
end # module
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sanitized
|
4
|
+
|
5
|
+
##
|
6
|
+
# = Description
|
7
|
+
#
|
8
|
+
# ActiveModel::Type to cast and sanitize a model's String attribute according to the
|
9
|
+
# options specified on initialisation.
|
10
|
+
#
|
11
|
+
# attribute :attr_name, Sanitized::String.new(:squish, :upcase), default: 'CodeMeister'
|
12
|
+
#
|
13
|
+
# Can optionally include a custom block:
|
14
|
+
# type_cast = Sanitized::String.new(:squish, :upcase) do |value|
|
15
|
+
# ... custome code ...
|
16
|
+
# end
|
17
|
+
# attribute :attr_name, type_cast, default: 'CodeMeister'
|
18
|
+
#
|
19
|
+
class String < ::ActiveModel::Type::String
|
20
|
+
|
21
|
+
# ======================================================================
|
22
|
+
# Macros
|
23
|
+
# ======================================================================
|
24
|
+
|
25
|
+
include Sanitized::Base
|
26
|
+
|
27
|
+
|
28
|
+
|
29
|
+
# ======================================================================
|
30
|
+
# Class Methods
|
31
|
+
# ======================================================================
|
32
|
+
|
33
|
+
##
|
34
|
+
# Returns a Hash of valid options with the other options they are exclusive with
|
35
|
+
#
|
36
|
+
def self.valid_options
|
37
|
+
case_opts = [:capitalize, :camelcase, :camelize, :dasherize, :downcase, :humanize,
|
38
|
+
:parameterize, :swapcase, :titlecase, :titleize, :underscore, :upcase,
|
39
|
+
:upcase_first]
|
40
|
+
{
|
41
|
+
capitalize: case_opts,
|
42
|
+
camelcase: case_opts,
|
43
|
+
camelize: case_opts,
|
44
|
+
chomp: [],
|
45
|
+
dasherize: case_opts,
|
46
|
+
downcase: case_opts,
|
47
|
+
humanize: case_opts,
|
48
|
+
lstrip: [],
|
49
|
+
parameterize: case_opts,
|
50
|
+
rstrip: [],
|
51
|
+
singularize: [],
|
52
|
+
squish: [],
|
53
|
+
strip: [],
|
54
|
+
swapcase: case_opts,
|
55
|
+
titlecase: case_opts,
|
56
|
+
titleize: case_opts,
|
57
|
+
underscore: case_opts,
|
58
|
+
upcase: case_opts,
|
59
|
+
upcase_first: case_opts
|
60
|
+
}
|
61
|
+
end
|
62
|
+
end # class Type
|
63
|
+
end # module
|
data/lib/sanitized.rb
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'sanitized/base'
|
4
|
+
require_relative 'sanitized/big_integer'
|
5
|
+
require_relative 'sanitized/date_time'
|
6
|
+
require_relative 'sanitized/decimal'
|
7
|
+
require_relative 'sanitized/float'
|
8
|
+
require_relative 'sanitized/integer'
|
9
|
+
require_relative 'sanitized/string'
|
metadata
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sanitized
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.7.4
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- CodeMeister
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-09-19 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activerecord
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 5.0.0.beta1
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 5.0.0.beta1
|
27
|
+
description: " An elegant solution for sanitizing user input. Cleaning & reformatting
|
28
|
+
user data is a necessary chore for all developers; but it no longer needs to
|
29
|
+
be time-consuming! The Sanitized suite of helpers allow you to quickly sanitize
|
30
|
+
any ActiveRecord attribute, and easily add your own custom code to catch those
|
31
|
+
edge cases. It will save you a surprisingly large amount of time! "
|
32
|
+
email: sanitized@codemeister.dev
|
33
|
+
executables: []
|
34
|
+
extensions: []
|
35
|
+
extra_rdoc_files: []
|
36
|
+
files:
|
37
|
+
- lib/sanitized.rb
|
38
|
+
- lib/sanitized/base.rb
|
39
|
+
- lib/sanitized/big_integer.rb
|
40
|
+
- lib/sanitized/date_time.rb
|
41
|
+
- lib/sanitized/decimal.rb
|
42
|
+
- lib/sanitized/float.rb
|
43
|
+
- lib/sanitized/integer.rb
|
44
|
+
- lib/sanitized/string.rb
|
45
|
+
homepage: https://github.com/Rubology/sanitized
|
46
|
+
licenses:
|
47
|
+
- MIT
|
48
|
+
metadata:
|
49
|
+
homepage_uri: https://github.com/Rubology/sanitized
|
50
|
+
source_code_uri: https://github.com/Rubology/sanitized
|
51
|
+
changelog_uri: https://github.com/Rubology/sanitized/blob/master/CHANGELOG.md
|
52
|
+
post_install_message:
|
53
|
+
rdoc_options: []
|
54
|
+
require_paths:
|
55
|
+
- lib
|
56
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '2.5'
|
61
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
62
|
+
requirements:
|
63
|
+
- - ">="
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
requirements: []
|
67
|
+
rubygems_version: 3.2.27
|
68
|
+
signing_key:
|
69
|
+
specification_version: 4
|
70
|
+
summary: An elegant solution for sanitizing user input, with a number of built-in
|
71
|
+
options or your own custom code.
|
72
|
+
test_files: []
|