sanitize 6.1.2 → 7.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 +4 -4
- data/{HISTORY.md → CHANGELOG.md} +40 -14
- data/LICENSE +3 -1
- data/README.md +120 -238
- data/lib/sanitize/config/basic.rb +15 -15
- data/lib/sanitize/config/default.rb +45 -45
- data/lib/sanitize/config/relaxed.rb +136 -32
- data/lib/sanitize/config/restricted.rb +2 -2
- data/lib/sanitize/config.rb +12 -14
- data/lib/sanitize/css.rb +309 -303
- data/lib/sanitize/transformers/clean_cdata.rb +9 -9
- data/lib/sanitize/transformers/clean_comment.rb +9 -9
- data/lib/sanitize/transformers/clean_css.rb +59 -55
- data/lib/sanitize/transformers/clean_doctype.rb +15 -15
- data/lib/sanitize/transformers/clean_element.rb +220 -237
- data/lib/sanitize/version.rb +3 -1
- data/lib/sanitize.rb +38 -38
- data/test/common.rb +4 -3
- data/test/test_clean_comment.rb +26 -25
- data/test/test_clean_css.rb +14 -13
- data/test/test_clean_doctype.rb +21 -20
- data/test/test_clean_element.rb +258 -273
- data/test/test_config.rb +22 -21
- data/test/test_malicious_css.rb +20 -19
- data/test/test_malicious_html.rb +100 -99
- data/test/test_parser.rb +26 -25
- data/test/test_sanitize.rb +70 -69
- data/test/test_sanitize_css.rb +152 -114
- data/test/test_transformers.rb +81 -83
- metadata +14 -43
@@ -1,30 +1,30 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Sanitize
|
4
4
|
module Config
|
5
5
|
BASIC = freeze_config(
|
6
|
-
:
|
6
|
+
elements: RESTRICTED[:elements] + %w[
|
7
7
|
a abbr blockquote br cite code dd dfn dl dt kbd li mark ol p pre q s
|
8
8
|
samp small strike sub sup time ul var
|
9
9
|
],
|
10
10
|
|
11
|
-
:
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
11
|
+
attributes: {
|
12
|
+
"a" => %w[href],
|
13
|
+
"abbr" => %w[title],
|
14
|
+
"blockquote" => %w[cite],
|
15
|
+
"dfn" => %w[title],
|
16
|
+
"q" => %w[cite],
|
17
|
+
"time" => %w[datetime pubdate]
|
18
18
|
},
|
19
19
|
|
20
|
-
:
|
21
|
-
|
20
|
+
add_attributes: {
|
21
|
+
"a" => {"rel" => "nofollow"}
|
22
22
|
},
|
23
23
|
|
24
|
-
:
|
25
|
-
|
26
|
-
|
27
|
-
|
24
|
+
protocols: {
|
25
|
+
"a" => {"href" => ["ftp", "http", "https", "mailto", :relative]},
|
26
|
+
"blockquote" => {"cite" => ["http", "https", :relative]},
|
27
|
+
"q" => {"cite" => ["http", "https", :relative]}
|
28
28
|
}
|
29
29
|
)
|
30
30
|
end
|
@@ -1,55 +1,55 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Sanitize
|
4
4
|
module Config
|
5
5
|
DEFAULT = freeze_config(
|
6
6
|
# HTML attributes to add to specific elements. By default, no attributes
|
7
7
|
# are added.
|
8
|
-
:
|
8
|
+
add_attributes: {},
|
9
9
|
|
10
10
|
# Whether or not to allow HTML comments. Allowing comments is strongly
|
11
11
|
# discouraged, since IE allows script execution within conditional
|
12
12
|
# comments.
|
13
|
-
:
|
13
|
+
allow_comments: false,
|
14
14
|
|
15
15
|
# Whether or not to allow well-formed HTML doctype declarations such as
|
16
16
|
# "<!DOCTYPE html>" when sanitizing a document. This setting is ignored
|
17
17
|
# when sanitizing fragments.
|
18
|
-
:
|
18
|
+
allow_doctype: false,
|
19
19
|
|
20
20
|
# HTML attributes to allow in specific elements. By default, no attributes
|
21
21
|
# are allowed. Use the symbol :data to indicate that arbitrary HTML5
|
22
22
|
# data-* attributes should be allowed.
|
23
|
-
:
|
23
|
+
attributes: {},
|
24
24
|
|
25
25
|
# CSS sanitization settings.
|
26
|
-
:
|
26
|
+
css: {
|
27
27
|
# Whether or not to allow CSS comments.
|
28
|
-
:
|
28
|
+
allow_comments: false,
|
29
29
|
|
30
30
|
# Whether or not to allow browser compatibility hacks such as the IE *
|
31
31
|
# and _ hacks. These are generally harmless, but technically result in
|
32
32
|
# invalid CSS.
|
33
|
-
:
|
33
|
+
allow_hacks: false,
|
34
34
|
|
35
35
|
# CSS at-rules to allow that may not have associated blocks (e.g.
|
36
36
|
# "import").
|
37
37
|
#
|
38
38
|
# https://developer.mozilla.org/en-US/docs/Web/CSS/At-rule
|
39
|
-
:
|
39
|
+
at_rules: [],
|
40
40
|
|
41
41
|
# CSS at-rules to allow whose blocks may contain properties (e.g.
|
42
42
|
# "font-face").
|
43
|
-
:
|
43
|
+
at_rules_with_properties: [],
|
44
44
|
|
45
45
|
# CSS at-rules to allow whose blocks may contain styles (e.g. "media").
|
46
|
-
:
|
46
|
+
at_rules_with_styles: [],
|
47
47
|
|
48
48
|
# CSS properties to allow.
|
49
|
-
:
|
49
|
+
properties: [],
|
50
50
|
|
51
51
|
# URL protocols to allow in CSS URLs.
|
52
|
-
:
|
52
|
+
protocols: []
|
53
53
|
},
|
54
54
|
|
55
55
|
# HTML elements to allow. By default, no elements are allowed (which means
|
@@ -59,16 +59,16 @@ class Sanitize
|
|
59
59
|
# elements (elements in the MathML or SVG namespaces). Do not add `math`
|
60
60
|
# or `svg` to this list! If you do, you may create a security
|
61
61
|
# vulnerability in your application.
|
62
|
-
:
|
62
|
+
elements: [],
|
63
63
|
|
64
64
|
# HTML parsing options to pass to Nokogumbo.
|
65
65
|
# https://github.com/rubys/nokogumbo/tree/v2.0.1#parsing-options
|
66
|
-
:
|
66
|
+
parser_options: {},
|
67
67
|
|
68
68
|
# URL handling protocols to allow in specific attributes. By default, no
|
69
69
|
# protocols are allowed. Use :relative in place of a protocol if you want
|
70
70
|
# to allow relative URLs sans protocol.
|
71
|
-
:
|
71
|
+
protocols: {},
|
72
72
|
|
73
73
|
# If this is true, Sanitize will remove the contents of any filtered
|
74
74
|
# elements in addition to the elements themselves. By default, Sanitize
|
@@ -78,45 +78,45 @@ class Sanitize
|
|
78
78
|
# If this is an Array or Set of element names, then only the contents of
|
79
79
|
# the specified elements (when filtered) will be removed, and the contents
|
80
80
|
# of all other filtered elements will be left behind.
|
81
|
-
:
|
81
|
+
remove_contents: %w[
|
82
82
|
iframe math noembed noframes noscript plaintext script style svg xmp
|
83
83
|
],
|
84
84
|
|
85
85
|
# Transformers allow you to filter or alter nodes using custom logic. See
|
86
86
|
# README.md for details and examples.
|
87
|
-
:
|
87
|
+
transformers: [],
|
88
88
|
|
89
89
|
# Elements which, when removed, should have their contents surrounded by
|
90
90
|
# values specified with `before` and `after` keys to preserve readability.
|
91
91
|
# For example, `foo<div>bar</div>baz` will become 'foo bar baz' when the
|
92
92
|
# <div> is removed.
|
93
|
-
:
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
93
|
+
whitespace_elements: {
|
94
|
+
"address" => {before: " ", after: " "},
|
95
|
+
"article" => {before: " ", after: " "},
|
96
|
+
"aside" => {before: " ", after: " "},
|
97
|
+
"blockquote" => {before: " ", after: " "},
|
98
|
+
"br" => {before: " ", after: " "},
|
99
|
+
"dd" => {before: " ", after: " "},
|
100
|
+
"div" => {before: " ", after: " "},
|
101
|
+
"dl" => {before: " ", after: " "},
|
102
|
+
"dt" => {before: " ", after: " "},
|
103
|
+
"footer" => {before: " ", after: " "},
|
104
|
+
"h1" => {before: " ", after: " "},
|
105
|
+
"h2" => {before: " ", after: " "},
|
106
|
+
"h3" => {before: " ", after: " "},
|
107
|
+
"h4" => {before: " ", after: " "},
|
108
|
+
"h5" => {before: " ", after: " "},
|
109
|
+
"h6" => {before: " ", after: " "},
|
110
|
+
"header" => {before: " ", after: " "},
|
111
|
+
"hgroup" => {before: " ", after: " "},
|
112
|
+
"hr" => {before: " ", after: " "},
|
113
|
+
"li" => {before: " ", after: " "},
|
114
|
+
"nav" => {before: " ", after: " "},
|
115
|
+
"ol" => {before: " ", after: " "},
|
116
|
+
"p" => {before: " ", after: " "},
|
117
|
+
"pre" => {before: " ", after: " "},
|
118
|
+
"section" => {before: " ", after: " "},
|
119
|
+
"ul" => {before: " ", after: " "}
|
120
120
|
}
|
121
121
|
)
|
122
122
|
end
|
@@ -1,46 +1,44 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Sanitize
|
4
4
|
module Config
|
5
5
|
RELAXED = freeze_config(
|
6
|
-
:
|
6
|
+
elements: BASIC[:elements] + %w[
|
7
7
|
address article aside bdi bdo body caption col colgroup data del div
|
8
8
|
figcaption figure footer h1 h2 h3 h4 h5 h6 head header hgroup hr html
|
9
9
|
img ins main nav rp rt ruby section span style summary table tbody
|
10
10
|
td tfoot th thead title tr wbr
|
11
11
|
],
|
12
12
|
|
13
|
-
:
|
13
|
+
allow_doctype: true,
|
14
14
|
|
15
|
-
:
|
16
|
-
:all
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
),
|
15
|
+
attributes: merge(BASIC[:attributes],
|
16
|
+
:all => %w[class dir hidden id lang style tabindex title translate],
|
17
|
+
"a" => %w[href hreflang name rel],
|
18
|
+
"col" => %w[span width],
|
19
|
+
"colgroup" => %w[span width],
|
20
|
+
"data" => %w[value],
|
21
|
+
"del" => %w[cite datetime],
|
22
|
+
"img" => %w[align alt border height src srcset width],
|
23
|
+
"ins" => %w[cite datetime],
|
24
|
+
"li" => %w[value],
|
25
|
+
"ol" => %w[reversed start type],
|
26
|
+
"style" => %w[media scoped type],
|
27
|
+
"table" => %w[align bgcolor border cellpadding cellspacing frame rules sortable summary width],
|
28
|
+
"td" => %w[abbr align axis colspan headers rowspan valign width],
|
29
|
+
"th" => %w[abbr align axis colspan headers rowspan scope sorted valign width],
|
30
|
+
"ul" => %w[type]),
|
32
31
|
|
33
|
-
:
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
),
|
32
|
+
protocols: merge(BASIC[:protocols],
|
33
|
+
"del" => {"cite" => ["http", "https", :relative]},
|
34
|
+
"img" => {"src" => ["http", "https", :relative]},
|
35
|
+
"ins" => {"cite" => ["http", "https", :relative]}),
|
38
36
|
|
39
|
-
:
|
40
|
-
:
|
41
|
-
:
|
37
|
+
css: {
|
38
|
+
allow_comments: true,
|
39
|
+
allow_hacks: true,
|
42
40
|
|
43
|
-
:
|
41
|
+
at_rules_with_properties: %w[
|
44
42
|
bottom-center
|
45
43
|
bottom-left
|
46
44
|
bottom-left-corner
|
@@ -61,19 +59,20 @@ class Sanitize
|
|
61
59
|
top-right-corner
|
62
60
|
],
|
63
61
|
|
64
|
-
:
|
62
|
+
at_rules_with_styles: %w[
|
65
63
|
-moz-keyframes
|
66
64
|
-o-keyframes
|
67
65
|
-webkit-keyframes
|
66
|
+
container
|
68
67
|
document
|
69
68
|
keyframes
|
70
69
|
media
|
71
70
|
supports
|
72
71
|
],
|
73
72
|
|
74
|
-
:
|
73
|
+
protocols: ["http", "https", :relative],
|
75
74
|
|
76
|
-
:
|
75
|
+
properties: %w[
|
77
76
|
-moz-appearance
|
78
77
|
-moz-background-inline-policy
|
79
78
|
-moz-box-sizing
|
@@ -333,6 +332,7 @@ class Sanitize
|
|
333
332
|
-webkit-text-decoration-color
|
334
333
|
-webkit-text-decoration-line
|
335
334
|
-webkit-text-decoration-style
|
335
|
+
-webkit-text-fill-color
|
336
336
|
-webkit-text-size-adjust
|
337
337
|
-webkit-touch-callout
|
338
338
|
-webkit-transform
|
@@ -349,6 +349,7 @@ class Sanitize
|
|
349
349
|
-webkit-user-drag
|
350
350
|
-webkit-wrap-flow
|
351
351
|
-webkit-wrap-through
|
352
|
+
accent-color
|
352
353
|
align-content
|
353
354
|
align-items
|
354
355
|
align-self
|
@@ -356,7 +357,10 @@ class Sanitize
|
|
356
357
|
alignment-baseline
|
357
358
|
all
|
358
359
|
anchor-point
|
360
|
+
anchor-name
|
361
|
+
anchor-scope
|
359
362
|
animation
|
363
|
+
animation-composition
|
360
364
|
animation-delay
|
361
365
|
animation-direction
|
362
366
|
animation-duration
|
@@ -364,11 +368,18 @@ class Sanitize
|
|
364
368
|
animation-iteration-count
|
365
369
|
animation-name
|
366
370
|
animation-play-state
|
371
|
+
animation-range
|
372
|
+
animation-range-end
|
373
|
+
animation-range-start
|
374
|
+
animation-timeline
|
367
375
|
animation-timing-function
|
376
|
+
appearance
|
377
|
+
aspect-ratio
|
368
378
|
azimuth
|
369
379
|
backface-visibility
|
370
380
|
background
|
371
381
|
background-attachment
|
382
|
+
background-blend-mode
|
372
383
|
background-clip
|
373
384
|
background-color
|
374
385
|
background-image
|
@@ -379,24 +390,54 @@ class Sanitize
|
|
379
390
|
baseline-shift
|
380
391
|
binding
|
381
392
|
bleed
|
393
|
+
baseline-source
|
394
|
+
block-ellipsis
|
395
|
+
block-size
|
382
396
|
bookmark-label
|
383
397
|
bookmark-level
|
384
398
|
bookmark-state
|
385
399
|
border
|
400
|
+
border-block
|
401
|
+
border-block-color
|
402
|
+
border-block-end
|
403
|
+
border-block-end-color
|
404
|
+
border-block-end-style
|
405
|
+
border-block-end-width
|
406
|
+
border-block-start
|
407
|
+
border-block-start-color
|
408
|
+
border-block-start-style
|
409
|
+
border-block-start-width
|
410
|
+
border-block-style
|
411
|
+
border-block-width
|
386
412
|
border-bottom
|
387
413
|
border-bottom-color
|
388
414
|
border-bottom-left-radius
|
389
415
|
border-bottom-right-radius
|
390
416
|
border-bottom-style
|
391
417
|
border-bottom-width
|
418
|
+
border-boundary
|
392
419
|
border-collapse
|
393
420
|
border-color
|
421
|
+
border-end-end-radius
|
422
|
+
border-end-start-radius
|
394
423
|
border-image
|
395
424
|
border-image-outset
|
396
425
|
border-image-repeat
|
397
426
|
border-image-slice
|
398
427
|
border-image-source
|
399
428
|
border-image-width
|
429
|
+
border-inline
|
430
|
+
border-inline-color
|
431
|
+
border-inline-end
|
432
|
+
border-inline-end-color
|
433
|
+
border-inline-end-style
|
434
|
+
border-inline-end-width
|
435
|
+
border-inline-start
|
436
|
+
border-inline-start-color
|
437
|
+
border-inline-start-style
|
438
|
+
border-inline-start-width
|
439
|
+
border-inline-style
|
440
|
+
border-inline-width
|
400
441
|
border-left
|
401
442
|
border-left-color
|
402
443
|
border-left-style
|
@@ -407,6 +448,8 @@ class Sanitize
|
|
407
448
|
border-right-style
|
408
449
|
border-right-width
|
409
450
|
border-spacing
|
451
|
+
border-start-end-radius
|
452
|
+
border-start-start-radius
|
410
453
|
border-style
|
411
454
|
border-top
|
412
455
|
border-top-color
|
@@ -426,15 +469,20 @@ class Sanitize
|
|
426
469
|
break-inside
|
427
470
|
caption-side
|
428
471
|
chains
|
472
|
+
caret
|
473
|
+
caret-color
|
474
|
+
caret-shape
|
429
475
|
clear
|
430
476
|
clip
|
431
477
|
clip-path
|
432
478
|
clip-rule
|
433
479
|
color
|
434
480
|
color-interpolation
|
481
|
+
color-adjust
|
435
482
|
color-interpolation-filters
|
436
483
|
color-profile
|
437
484
|
color-rendering
|
485
|
+
color-scheme
|
438
486
|
column-count
|
439
487
|
column-fill
|
440
488
|
column-gap
|
@@ -446,7 +494,17 @@ class Sanitize
|
|
446
494
|
column-width
|
447
495
|
columns
|
448
496
|
contain
|
497
|
+
contain-intrinsic-block-size
|
498
|
+
contain-intrinsic-height
|
499
|
+
contain-intrinsic-inline-size
|
500
|
+
contain-intrinsic-size
|
501
|
+
contain-intrinsic-width
|
502
|
+
container
|
503
|
+
container-name
|
504
|
+
container-type
|
449
505
|
content
|
506
|
+
content-visibility
|
507
|
+
continue
|
450
508
|
counter-increment
|
451
509
|
counter-reset
|
452
510
|
counter-set
|
@@ -486,20 +544,33 @@ class Sanitize
|
|
486
544
|
font-feature-settings
|
487
545
|
font-kerning
|
488
546
|
font-language-override
|
547
|
+
font-optical-sizing
|
548
|
+
font-palette
|
489
549
|
font-size
|
490
550
|
font-size-adjust
|
491
551
|
font-stretch
|
492
552
|
font-style
|
493
553
|
font-synthesis
|
554
|
+
font-synthesis-position
|
555
|
+
font-synthesis-small-caps
|
556
|
+
font-synthesis-style
|
557
|
+
font-synthesis-weight
|
494
558
|
font-variant
|
495
559
|
font-variant-alternates
|
496
560
|
font-variant-caps
|
497
561
|
font-variant-east-asian
|
562
|
+
font-variant-emoji
|
498
563
|
font-variant-ligatures
|
499
564
|
font-variant-numeric
|
500
565
|
font-variant-position
|
566
|
+
font-variation-settings
|
501
567
|
font-weight
|
502
568
|
glyph-orientation-horizontal
|
569
|
+
font-width
|
570
|
+
footnote-display
|
571
|
+
footnote-policy
|
572
|
+
forced-color-adjust
|
573
|
+
gap
|
503
574
|
glyph-orientation-vertical
|
504
575
|
grid
|
505
576
|
grid-area
|
@@ -658,22 +729,33 @@ class Sanitize
|
|
658
729
|
tab-size
|
659
730
|
table-layout
|
660
731
|
text-align
|
732
|
+
text-align-all
|
661
733
|
text-align-last
|
662
734
|
text-anchor
|
663
735
|
text-combine-horizontal
|
736
|
+
text-autospace
|
737
|
+
text-box
|
738
|
+
text-box-edge
|
739
|
+
text-box-trim
|
664
740
|
text-combine-upright
|
665
741
|
text-decoration
|
666
742
|
text-decoration-color
|
667
743
|
text-decoration-line
|
668
744
|
text-decoration-skip
|
745
|
+
text-decoration-skip-box
|
669
746
|
text-decoration-skip-ink
|
747
|
+
text-decoration-skip-inset
|
748
|
+
text-decoration-skip-self
|
749
|
+
text-decoration-skip-spaces
|
670
750
|
text-decoration-style
|
671
751
|
text-decoration-thickness
|
672
752
|
text-emphasis
|
673
753
|
text-emphasis-color
|
674
754
|
text-emphasis-position
|
755
|
+
text-emphasis-skip
|
675
756
|
text-emphasis-style
|
676
757
|
text-height
|
758
|
+
text-group-align
|
677
759
|
text-indent
|
678
760
|
text-justify
|
679
761
|
text-orientation
|
@@ -682,12 +764,19 @@ class Sanitize
|
|
682
764
|
text-shadow
|
683
765
|
text-size-adjust
|
684
766
|
text-space-collapse
|
767
|
+
text-spacing
|
768
|
+
text-spacing-trim
|
685
769
|
text-transform
|
770
|
+
text-underline-offset
|
686
771
|
text-underline-position
|
687
772
|
text-wrap
|
773
|
+
text-wrap-mode
|
774
|
+
text-wrap-style
|
775
|
+
timeline-scope
|
688
776
|
top
|
689
777
|
touch-action
|
690
778
|
transform
|
779
|
+
transform-box
|
691
780
|
transform-origin
|
692
781
|
transform-style
|
693
782
|
transition
|
@@ -695,9 +784,18 @@ class Sanitize
|
|
695
784
|
transition-duration
|
696
785
|
transition-property
|
697
786
|
transition-timing-function
|
787
|
+
translate
|
698
788
|
unicode-bidi
|
699
789
|
unicode-range
|
790
|
+
user-select
|
700
791
|
vertical-align
|
792
|
+
view-timeline
|
793
|
+
view-timeline-axis
|
794
|
+
view-timeline-inset
|
795
|
+
view-timeline-name
|
796
|
+
view-transition-class
|
797
|
+
view-transition-group
|
798
|
+
view-transition-name
|
701
799
|
visibility
|
702
800
|
voice-balance
|
703
801
|
voice-duration
|
@@ -709,13 +807,19 @@ class Sanitize
|
|
709
807
|
voice-volume
|
710
808
|
volume
|
711
809
|
white-space
|
810
|
+
white-space-collapse
|
811
|
+
white-space-trim
|
712
812
|
widows
|
713
813
|
width
|
714
814
|
will-change
|
715
815
|
word-break
|
816
|
+
word-space-transform
|
716
817
|
word-spacing
|
717
818
|
word-wrap
|
819
|
+
wrap-after
|
820
|
+
wrap-before
|
718
821
|
wrap-flow
|
822
|
+
wrap-inside
|
719
823
|
wrap-through
|
720
824
|
writing-mode
|
721
825
|
z-index
|
data/lib/sanitize/config.rb
CHANGED
@@ -1,16 +1,15 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "set"
|
4
4
|
|
5
5
|
class Sanitize
|
6
6
|
module Config
|
7
|
-
|
8
7
|
# Deeply freezes and returns the given configuration Hash.
|
9
8
|
def self.freeze_config(config)
|
10
9
|
if Hash === config
|
11
|
-
config.each_value {|c| freeze_config(c) }
|
10
|
+
config.each_value { |c| freeze_config(c) }
|
12
11
|
elsif Array === config || Set === config
|
13
|
-
config.each {|c| freeze_config(c) }
|
12
|
+
config.each { |c| freeze_config(c) }
|
14
13
|
end
|
15
14
|
|
16
15
|
config.freeze
|
@@ -22,11 +21,11 @@ class Sanitize
|
|
22
21
|
# This is the safest way to use a built-in Sanitize config as the basis for
|
23
22
|
# your own custom config.
|
24
23
|
def self.merge(config, other_config = {})
|
25
|
-
raise ArgumentError,
|
26
|
-
raise ArgumentError,
|
24
|
+
raise ArgumentError, "config must be a Hash" unless Hash === config
|
25
|
+
raise ArgumentError, "other_config must be a Hash" unless Hash === other_config
|
27
26
|
|
28
27
|
merged = {}
|
29
|
-
keys
|
28
|
+
keys = Set.new(config.keys + other_config.keys)
|
30
29
|
|
31
30
|
keys.each do |key|
|
32
31
|
oldval = config[key]
|
@@ -34,12 +33,12 @@ class Sanitize
|
|
34
33
|
if other_config.has_key?(key)
|
35
34
|
newval = other_config[key]
|
36
35
|
|
37
|
-
if Hash === oldval && Hash === newval
|
38
|
-
|
36
|
+
merged[key] = if Hash === oldval && Hash === newval
|
37
|
+
oldval.empty? ? newval.dup : merge(oldval, newval)
|
39
38
|
elsif Array === newval && key != :transformers
|
40
|
-
|
39
|
+
Set.new(newval)
|
41
40
|
else
|
42
|
-
|
41
|
+
can_dupe?(newval) ? newval.dup : newval
|
43
42
|
end
|
44
43
|
else
|
45
44
|
merged[key] = can_dupe?(oldval) ? oldval.dup : oldval
|
@@ -52,9 +51,8 @@ class Sanitize
|
|
52
51
|
# Returns `true` if `dup` may be safely called on _value_, `false`
|
53
52
|
# otherwise.
|
54
53
|
def self.can_dupe?(value)
|
55
|
-
!(
|
54
|
+
!(value == true || value == false || value.nil? || Method === value || Numeric === value || Symbol === value)
|
56
55
|
end
|
57
56
|
private_class_method :can_dupe?
|
58
|
-
|
59
57
|
end
|
60
58
|
end
|