diff --git a/CHANGELOG.md b/CHANGELOG.md index b9b2cdf..52e1cbe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ ## Ruby CSS Parser CHANGELOG ### Unreleased +* Speed up `RuleSet::Declarations#to_s` ~20x: its clean-up regexp matched the empty string at every character (`[\n\r\f\t]*`), making `gsub!` replace at every position; the unreachable `\s+$` branch is dropped, output unchanged +* Allocate less in `RuleSet`: skip the downcased copy of already normalized property names, and build dimension shorthands without enumerators ### Version 3.3.0 * Fix Arbitrary local-file read via attacker-controlled `@import` diff --git a/lib/css_parser/rule_set.rb b/lib/css_parser/rule_set.rb index 453c34f..cff4bd7 100644 --- a/lib/css_parser/rule_set.rb +++ b/lib/css_parser/rule_set.rb @@ -18,6 +18,8 @@ class RuleSet NUMBER_OF_DIMENSIONS = 4 + NORMALIZED_PROPERTY_RX = /\A[-a-z0-9_]+\z/.freeze + DIMENSIONS = [ ['margin', %w[margin-top margin-right margin-bottom margin-left]], ['padding', %w[padding-top padding-right padding-bottom padding-left]], @@ -205,8 +207,7 @@ def to_s(options = {}) importance = options[:force_important] || value.important ? ' !important' : '' memo << "#{prop}: #{value.value}#{importance}; " end - # TODO: Clean-up regexp doesn't seem to work - str.gsub!(/^[\s^({)]+|[\n\r\f\t]*|\s+$/mx, '') + str.gsub!(/^[\s^({)]+|[\n\r\f\t]+/, '') str.strip! str end @@ -226,7 +227,10 @@ def ==(other) attr_writer :declarations def normalize_property(property) - property = property.to_s.downcase + property = property.to_s + return property if property.match?(NORMALIZED_PROPERTY_RX) + + property = property.downcase property.strip! property end @@ -584,10 +588,11 @@ def create_dimensions_shorthand! # :nodoc: return if declarations.size < NUMBER_OF_DIMENSIONS DIMENSIONS.each do |property, dimensions| - values = DIMENSION_DIRECTIONS.each_with_index.with_object({}) do |(side, index), result| + values = {} + DIMENSION_DIRECTIONS.each_with_index do |side, index| next unless (declaration = declarations[dimensions[index]]) - result[side] = declaration.value + values[side] = declaration.value end # All four dimensions must be present