From 65e95d69382b612788fa57967c3f7b778be5bc2f Mon Sep 17 00:00:00 2001 From: Ryan Grove Date: Fri, 17 Apr 2015 20:44:10 -0700 Subject: [PATCH] Make at-rules more configurable; add proper @page support. This includes a Crass version bump to 1.0.2 to fix a CSS parsing bug that prevented `@page` rules from being parsed properly. Fixes #111. --- HISTORY.md | 36 +++++++++++++++++++++++++++++++++- lib/sanitize/config/default.rb | 13 ++++++++++-- lib/sanitize/config/relaxed.rb | 33 ++++++++++++++++++++++++++++++- lib/sanitize/css.rb | 17 ++++++++-------- lib/sanitize/version.rb | 2 +- sanitize.gemspec | 2 +- test/test_sanitize_css.rb | 25 +++++++++++++++++++++++ 7 files changed, 113 insertions(+), 15 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index 7056d31..8ca0aec 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,11 +1,45 @@ Sanitize History ================================================================================ -Version 3.2.0 (git) +Version 4.0.0 (git) ------------------- +### Potentially breaking changes + +* Added two new CSS config settings, `:at_rules_with_properties` and + `:at_rules_with_styles`. These allow you to define which at-rules should be + allowed to contain properties and which should be allowed to contain style + rules. Previously this was hard-coded internally. [#111][111] + + The previous `:at_rules` setting still exists, and defines at-rules that may + not have associated blocks, such as `@import`. If you have a custom config + that contains an `:at_rules` setting, you may need to move rules can have + blocks to either `:at_rules_with_properties` or `:at_rules_with_styles`. + + See Sanitize's relaxed config for an example. + +### Other changes + +* Added full support for CSS `@page` rules in the relaxed config, including + support for all page-margin box rules (such as `@top-left`, `@bottom-center`, + etc.) + +* Added the following CSS at-rules to the relaxed config: + + - `@-moz-keyframes` + - `@-o-keyframes` + - `@-webkit-keyframes` + - `@document` + +* Added the `size` CSS property to the relaxed config. + * Small performance improvements. +* Fixed: Upgraded Crass to 1.0.2 to pick up a fix that affected the parsing of + CSS `@page` rules. + +[111]:https://github.com/rgrove/sanitize/issues/111 + Version 3.1.2 (2015-02-22) -------------------------- diff --git a/lib/sanitize/config/default.rb b/lib/sanitize/config/default.rb index 93e892c..09e1348 100644 --- a/lib/sanitize/config/default.rb +++ b/lib/sanitize/config/default.rb @@ -32,11 +32,20 @@ module Config # invalid CSS. :allow_hacks => false, - # CSS @ rules to allow. + # CSS at-rules to allow that may not have associated blocks (e.g. + # "import"). + # # https://developer.mozilla.org/en-US/docs/Web/CSS/At-rule :at_rules => [], - # CSS style properties to allow. + # CSS at-rules to allow whose blocks may contain properties (e.g. + # "font-face"). + :at_rules_with_properties => [], + + # CSS at-rules to allow whose blocks may contain styles (e.g. "media"). + :at_rules_with_styles => [], + + # CSS properties to allow. :properties => [], # URL protocols to allow in CSS URLs. diff --git a/lib/sanitize/config/relaxed.rb b/lib/sanitize/config/relaxed.rb index ab479c2..1a2793d 100644 --- a/lib/sanitize/config/relaxed.rb +++ b/lib/sanitize/config/relaxed.rb @@ -40,7 +40,37 @@ module Config :allow_comments => true, :allow_hacks => true, - :at_rules => %w[font-face keyframes media page supports], + :at_rules_with_properties => %w[ + bottom-center + bottom-left + bottom-left-corner + bottom-right + bottom-right-corner + font-face + left-bottom + left-middle + left-top + page + right-bottom + right-middle + right-top + top-center + top-left + top-left-corner + top-right + top-right-corner + ], + + :at_rules_with_styles => %w[ + -moz-keyframes + -o-keyframes + -webkit-keyframes + document + keyframes + media + supports + ], + :protocols => ['http', 'https', :relative], :properties => %w[ @@ -484,6 +514,7 @@ module Config quotes resize right + size tab-size table-layout text-align diff --git a/lib/sanitize/css.rb b/lib/sanitize/css.rb index 3ec4a8c..bfea7dd 100644 --- a/lib/sanitize/css.rb +++ b/lib/sanitize/css.rb @@ -6,12 +6,6 @@ class Sanitize; class CSS attr_reader :config - # Names of CSS at-rules whose blocks may contain properties. - AT_RULES_WITH_PROPERTIES = Set.new(%w[font-face page]) - - # Names of CSS at-rules whose blocks may contain style rules. - AT_RULES_WITH_STYLES = Set.new(%w[document media supports]) - # -- Class Methods ----------------------------------------------------------- # Sanitizes inline CSS style properties. @@ -42,6 +36,11 @@ def self.tree!(tree, config = {}) # _config_. def initialize(config = {}) @config = Config.merge(Config::DEFAULT[:css], config[:css] || config) + + @at_rules_with_properties = Set.new(@config[:at_rules_with_properties]) + @at_rules_with_styles = Set.new(@config[:at_rules_with_styles]) + + @at_rules = @at_rules_with_properties + @at_rules_with_styles + @config[:at_rules] end # Sanitizes inline CSS style properties. @@ -154,16 +153,16 @@ def tree!(tree) # current config doesn't allow this at-rule. def at_rule!(rule) name = rule[:name].downcase - return nil unless @config[:at_rules].include?(name) + return nil unless @at_rules.include?(name) - if AT_RULES_WITH_STYLES.include?(name) + if @at_rules_with_styles.include?(name) styles = Crass::Parser.parse_rules(rule[:block], :preserve_comments => @config[:allow_comments], :preserve_hacks => @config[:allow_hacks]) rule[:block] = tree!(styles) - elsif AT_RULES_WITH_PROPERTIES.include?(name) + elsif @at_rules_with_properties.include?(name) props = Crass::Parser.parse_properties(rule[:block], :preserve_comments => @config[:allow_comments], :preserve_hacks => @config[:allow_hacks]) diff --git a/lib/sanitize/version.rb b/lib/sanitize/version.rb index a5d83f6..2abf5f2 100644 --- a/lib/sanitize/version.rb +++ b/lib/sanitize/version.rb @@ -1,5 +1,5 @@ # encoding: utf-8 class Sanitize - VERSION = '3.2.0' + VERSION = '4.0.0' end diff --git a/sanitize.gemspec b/sanitize.gemspec index 87cea5f..34699c5 100644 --- a/sanitize.gemspec +++ b/sanitize.gemspec @@ -17,7 +17,7 @@ Gem::Specification.new do |s| s.required_rubygems_version = Gem::Requirement.new('>= 1.2.0') # Runtime dependencies. - s.add_dependency('crass', '~> 1.0.1') + s.add_dependency('crass', '~> 1.0.2') s.add_dependency('nokogiri', '>= 1.4.4') s.add_dependency('nokogumbo', '1.2.0') diff --git a/test/test_sanitize_css.rb b/test/test_sanitize_css.rb index 641e547..3241f69 100644 --- a/test/test_sanitize_css.rb +++ b/test/test_sanitize_css.rb @@ -245,5 +245,30 @@ } ].strip end + + it 'should parse @page rules properly' do + css = %[ + @page { margin: 2cm } /* All margins set to 2cm */ + + @page :right { + @top-center { content: "Preliminary edition" } + @bottom-center { content: counter(page) } + } + + @page { + size: 8.5in 11in; + margin: 10%; + + @top-left { + content: "Hamlet"; + } + @top-right { + content: "Page " counter(page); + } + } + ].strip + + @relaxed.stylesheet(css).must_equal css + end end end