+# Nick's web site: css_clean_selectors filter. Remove unnecessary whitespace
+# from CSS selectors as this improves compatibility with old versions of IE.
+#
+# Copyright © 2020 Nick Bowler
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+class CssCleanSelectorsFilter < Nanoc::Filter
+ identifier :css_clean_selectors
+
+ require 'crass'
+
+ def run(content, params = {})
+ tree = Crass.parse(content, params)
+
+ queue = Array.new(tree)
+ while i = queue.shift do
+ if i[:node] == :at_rule
+ case i[:name]
+ when "media", "supports"
+ # Re-parse the block as a list of rules.
+ s = Crass::Parser.stringify(i[:block])
+ i[:block] = Crass::Parser.parse_rules(s, params)
+ queue += i[:block]
+ end
+ end
+
+ if i[:selector]
+ ts = i[:selector][:tokens]
+ ts.each_index do |i|
+ next if ts[i].nil? or ts[i][:node] != :delim
+ next if ts[i][:value] == '*'
+
+ ts[i-1] = nil if ts[i-1] and ts[i-1][:node] == :whitespace
+ ts[i+1] = nil if ts[i+1] and ts[i+1][:node] == :whitespace
+ end
+ end
+ end
+
+ return Crass::Parser.stringify(tree)
+ end
+end