Hello community, here is the log from the commit of package rubygem-loofah for openSUSE:Factory checked in at 2017-12-07 13:51:07 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/rubygem-loofah (Old) and /work/SRC/openSUSE:Factory/.rubygem-loofah.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "rubygem-loofah" Thu Dec 7 13:51:07 2017 rev:4 rq:533897 version:2.1.1 Changes: -------- --- /work/SRC/openSUSE:Factory/rubygem-loofah/rubygem-loofah.changes 2015-08-27 08:56:06.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.rubygem-loofah.new/rubygem-loofah.changes 2017-12-07 13:51:13.574977140 +0100 @@ -1,0 +2,9 @@ +Fri Oct 13 11:25:11 UTC 2017 - [email protected] + +- updated to version 2.1.1 + 2.1.1 / 2017-09-24 + + Bugfixes: + * Removed warning for unused variable. #124 (Thanks, @y-yagi!) + +------------------------------------------------------------------- Old: ---- loofah-2.0.3.gem New: ---- loofah-2.1.1.gem ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ rubygem-loofah.spec ++++++ --- /var/tmp/diff_new_pack.Mrxul4/_old 2017-12-07 13:51:14.074958931 +0100 +++ /var/tmp/diff_new_pack.Mrxul4/_new 2017-12-07 13:51:14.074958931 +0100 @@ -1,7 +1,7 @@ # # spec file for package rubygem-loofah # -# Copyright (c) 2015 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -24,7 +24,7 @@ # Name: rubygem-loofah -Version: 2.0.3 +Version: 2.1.1 Release: 0 %define mod_name loofah %define mod_full_name %{mod_name}-%{version} @@ -34,7 +34,7 @@ BuildRequires: %{ruby} BuildRequires: ruby-macros >= 5 Url: https://github.com/flavorjones/loofah -Source: http://rubygems.org/gems/%{mod_full_name}.gem +Source: https://rubygems.org/gems/%{mod_full_name}.gem Source1: gem2rpm.yml Summary: Loofah is a general library for manipulating and transforming License: MIT @@ -58,7 +58,7 @@ %install %gem_install \ - --doc-files="CHANGELOG.rdoc MIT-LICENSE.txt README.rdoc" \ + --doc-files="CHANGELOG.md MIT-LICENSE.txt README.rdoc" \ -f %gem_packages ++++++ loofah-2.0.3.gem -> loofah-2.1.1.gem ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/CHANGELOG.md new/CHANGELOG.md --- old/CHANGELOG.md 1970-01-01 01:00:00.000000000 +0100 +++ new/CHANGELOG.md 2017-09-25 03:11:14.000000000 +0200 @@ -0,0 +1,248 @@ +# Changelog + +## 2.1.1 / 2017-09-24 + +Bugfixes: + +* Removed warning for unused variable. #124 (Thanks, @y-yagi!) + + +## 2.1.0 / 2017-09-24 + +Notes: + +* Re-implemented CSS parsing and sanitization using the {crass}[https://github.com/rgrove/crass] library. #91 + + +Features: + +* Added :noopener HTML scrubber (Thanks, @tastycode!) +* Support `data` URIs with the following media types: text/plain, text/css, image/png, image/gif, image/jpeg, image/svg+xml. #101, #120. (Thanks, @mrpasquini!) + + +Bugfixes: + +* The :unprintable scrubber now scrubs unprintable characters in CDATA nodes (like `<script>`). #124 +* Allow negative values in CSS properties. Restores functionality that was reverted in v2.0.3. #91 + + +## 2.0.3 / 2015-08-17 + +Bug fixes: + +* Revert support for negative values in CSS properties due to slow performance. #90 (Related to #85.) + + +## 2.0.2 / 2015-05-05 + +Bug fixes: + +* Fix error with `#to_text` when Loofah::Helpers hadn't been required. #75 +* Allow multi-word data attributes. #84 (Thanks, @jstorimer!) +* Allow negative values in CSS properties. #85 (Thanks, @siddhartham!) + + +## 2.0.1 / 2014-08-21 + +Bug fixes: + +* Load RR correctly when running test files directly. (Thanks, @ktdreyer!) + + +Notes: + +* Extracted HTML5::Scrub#scrub_css_attribute to accommodate the Rails integration work. (Thanks, @kaspth!) + + +## 2.0.0 / 2014-05-09 + +Compatibility notes: + +* ActionView helpers now must be required explicitly: `require "loofah/helpers"` +* Support for Ruby 1.8.7 and prior has been dropped + +Enhancements: + +* HTML5 whitelist allows the following ... + * tags: `article`, `aside`, `bdi`, `bdo`, `canvas`, `command`, `datalist`, `details`, `figcaption`, `figure`, `footer`, `header`, `mark`, `meter`, `nav`, `output`, `section`, `summary`, `time` + * attributes: `data-*` (Thanks, Rafael Franca!) + * URI attributes: `poster` and `preload` +* Addition of the `:unprintable` scrubber to remove unprintable characters from text nodes. #65 (Thanks, Matt Swanson!) +* `Loofah.fragment` accepts an optional encoding argument, compatible with `Nokogiri::HTML::DocumentFragment.parse`. #62 (Thanks, Ben Atkins!) +* HTML5 sanitizers now remove attributes without values. (Thanks, Kasper Timm Hansen!) + +Bug fixes: + +* HTML5 sanitizers' CSS keyword check now actually works (broken in v2.0). Additional regression tests added. (Thanks, Kasper Timm Hansen!) +* HTML5 sanitizers now allow negative arguments to CSS. #64 (Thanks, Jon Calhoun!) + + +## 1.2.1 (2012-04-14) + +* Declaring encoding in html5/scrub.rb. Without this, use of the ruby -KU option would cause havoc. (#32) + + +## 1.2.0 (2011-08-08) + +Enhancements: + +* Loofah::Helpers.sanitize_css is a replacement for Rails's built-in sanitize_css helper. +* Improving ActionView integration. + + +## 1.1.0 (2011-08-08) + +Enhancements: + +* Additional HTML5lib whitelist elements (from html5lib 1524:80b5efe26230). + Up to date with HTML5lib ruby code as of 1723:7ee6a0331856. +* Whitelists (which are not part of the public API) are now Sets (were previously Arrays). +* Don't explode when encountering UTF-8 URIs. (#25, #29) + + +## 1.0.0 (2010-10-26) + +Notes: + +* Moved ActiveRecord functionality into `loofah-activerecord` gem. +* Removed DEPRECATIONS.rdoc documenting 0.3.0 API changes. + + +## 0.4.7 (2010-03-09) + +Enhancements: + +* New methods Loofah::HTML::Document#to_text and + Loofah::HTML::DocumentFragment#to_text do the right thing with + whitespace. Note that these methods are significantly slower than + #text. GH #12 +* Loofah::Elements::BLOCK_LEVEL contains a canonical list of HTML4 block-level4 elements. +* Loofah::HTML::Document#text and Loofah::HTML::DocumentFragment#text + will return unescaped HTML entities by passing :encode_special_chars => false. + + +## 0.4.4, 0.4.5, 0.4.6 (2010-02-01) + +Enhancements: + +* Loofah::HTML::Document#text and Loofah::HTML::DocumentFragment#text now escape HTML entities. + +Bug fixes: + +* Loofah::XssFoliate was not properly escaping HTML entities when implicitly scrubbing a string attribute. GH #17 + + +## 0.4.3 (2010-01-29) + +Enhancements: + +* All built-in scrubbers are accepted by ActiveRecord::Base.xss_foliate +* Loofah::XssFoliate.xss_foliate_all_models replaces use of the constant LOOFAH_XSS_FOLIATE_ALL_MODELS + +Miscellaneous: + +* Modified documentation for bootstrapping XssFoliate in a Rails app, + since the use of Bundler breaks the previously-documented method. To + be safe, always use an initializer file. + + +## 0.4.2 (2010-01-22) + +Enhancements: + +* Implemented Node#scrub! for scrubbing subtrees. +* Implemented NodeSet#scrub! for scrubbing a set of subtrees. +* Document.text now only serializes <body> contents (ignores <head>) +* <head>, <html> and <body> added to the HTML5lib whitelist. + +Bug fixes: + +* Supporting Rails apps that aren't loading ActiveRecord. GH #10 + +Miscellaneous: + +* Mailing list is now [email protected] / http://librelist.com +* IRC channel is now \#loofah on freenode. + + +## 0.4.1 (2009-11-23) + +Bugfix: + +* Manifest fixed. Whoops. + + +## 0.4.0 (2009-11-21) + +Enhancements: + +* Scrubber class introduced, allowing development of custom scrubbers. +* Added support for XML documents and fragments. +* Added :nofollow HTML scrubber (thanks Luke Melia!) +* Built-in scrubbing methods refactored to use Scrubber. + + + +## 0.3.1 (2009-10-12) + +Bug fixes: + +* Scrubbed Documents properly render html, head and body tags when serialized. + + +## 0.3.0 (2009-10-06) + +Enhancements: + +* New ActiveRecord extension `xss_foliate`, a drop-in replacement for xss_terminate[http://github.com/look/xss_terminate/tree/master]. +* Replacement methods for Rails's helpers, Loofah::Rails.sanitize and Loofah::Rails.strip_tags. +* Official support (and test coverage) for Rails versions 2.3, 2.2, 2.1, 2.0 and 1.2. + +Deprecations: + +* The methods strip_tags, whitewash, whitewash_document, sanitize, and + sanitize_document have been deprecated. See DEPRECATED.rdoc for + details on the equivalent calls with the post-0.2 API. + + +## 0.2.2 (2009-09-30) + +Enhancements: + +* ActiveRecord extension scrubs fields in a before_validation callback + (was previously in a before_save) + + +## 0.2.1 (2009-09-19) + +Enhancements: + +* when loaded in a Rails app, automatically extend ActiveRecord::Base + with html_fragment and html_document. GH #6 (Thanks Josh Nichols!) + +Bugfixes: + +* ActiveRecord scrubbing should generate strings instead of Document or + DocumentFragment objects. GH #5 +* init.rb fixed to support installation as a Rails plugin. GH #6 + (Thanks Josh Nichols!) + + +## 0.2.0 (2009-09-11) + +* Swank new API. +* ActiveRecord extension. +* Uses Nokogiri's Document and DocumentFragment for parsing. +* Updated html5lib codes and tests to revision 1384:b9d3153d7be7. +* Deprecated the Dryopteris sanitization methods. Will be removed in 0.3.0. +* Documentation! Hey! + + +## 0.1.2 (2009-04-30) + +* Added whitewashing -- removal of all attributes and namespaced nodes. You know, for microsofty HTML. + + +## 0.1.0 (2009-02-10) + +* Birthday! diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/CHANGELOG.rdoc new/CHANGELOG.rdoc --- old/CHANGELOG.rdoc 2015-08-17 20:10:12.000000000 +0200 +++ new/CHANGELOG.rdoc 1970-01-01 01:00:00.000000000 +0100 @@ -1,222 +0,0 @@ -= Changelog - -== 2.0.3 / 2015-08-17 - -Bug fixes: - -* Revert support for negative values in CSS properties due to slow performance. #90 (Related to #85.) - - -== 2.0.2 / 2015-05-05 - -Bug fixes: - -* Fix error with `#to_text` when Loofah::Helpers hadn't been required. #75 -* Allow multi-word data attributes. #84 (Thanks, @jstorimer!) -* Allow negative values in CSS properties. #85 (Thanks, @siddhartham!) - - -== 2.0.1 / 2014-08-21 - -Bug fixes: - -* Load RR correctly when running test files directly. (Thanks, @ktdreyer!) - - -Notes: - -* Extracted HTML5::Scrub#scrub_css_attribute to accommodate the Rails integration work. (Thanks, @kaspth!) - - -== 2.0.0 / 2014-05-09 - -Compatibility notes: - -* ActionView helpers now must be required explicitly: `require "loofah/helpers"` -* Support for Ruby 1.8.7 and prior has been dropped - -Enhancements: - -* HTML5 whitelist allows the following ... - * tags: `article`, `aside`, `bdi`, `bdo`, `canvas`, `command`, `datalist`, `details`, `figcaption`, `figure`, `footer`, `header`, `mark`, `meter`, `nav`, `output`, `section`, `summary`, `time` - * attributes: `data-*` (Thanks, Rafael Franca!) - * URI attributes: `poster` and `preload` -* Addition of the `:unprintable` scrubber to remove unprintable characters from text nodes. #65 (Thanks, Matt Swanson!) -* `Loofah.fragment` accepts an optional encoding argument, compatible with `Nokogiri::HTML::DocumentFragment.parse`. #62 (Thanks, Ben Atkins!) -* HTML5 sanitizers now remove attributes without values. (Thanks, Kasper Timm Hansen!) - -Bug fixes: - -* HTML5 sanitizers' CSS keyword check now actually works (broken in v2.0). Additional regression tests added. (Thanks, Kasper Timm Hansen!) -* HTML5 sanitizers now allow negative arguments to CSS. #64 (Thanks, Jon Calhoun!) - - -== 1.2.1 (2012-04-14) - -* Declaring encoding in html5/scrub.rb. Without this, use of the ruby -KU option would cause havoc. (#32) - - -== 1.2.0 (2011-08-08) - -Enhancements: - -* Loofah::Helpers.sanitize_css is a replacement for Rails's built-in sanitize_css helper. -* Improving ActionView integration. - - -== 1.1.0 (2011-08-08) - -Enhancements: - -* Additional HTML5lib whitelist elements (from html5lib 1524:80b5efe26230). - Up to date with HTML5lib ruby code as of 1723:7ee6a0331856. -* Whitelists (which are not part of the public API) are now Sets (were previously Arrays). -* Don't explode when encountering UTF-8 URIs. (#25, #29) - - -== 1.0.0 (2010-10-26) - -Notes: - -* Moved ActiveRecord functionality into `loofah-activerecord` gem. -* Removed DEPRECATIONS.rdoc documenting 0.3.0 API changes. - - -== 0.4.7 (2010-03-09) - -Enhancements: - -* New methods Loofah::HTML::Document#to_text and - Loofah::HTML::DocumentFragment#to_text do the right thing with - whitespace. Note that these methods are significantly slower than - #text. GH #12 -* Loofah::Elements::BLOCK_LEVEL contains a canonical list of HTML4 block-level4 elements. -* Loofah::HTML::Document#text and Loofah::HTML::DocumentFragment#text - will return unescaped HTML entities by passing :encode_special_chars => false. - - -== 0.4.4, 0.4.5, 0.4.6 (2010-02-01) - -Enhancements: - -* Loofah::HTML::Document#text and Loofah::HTML::DocumentFragment#text now escape HTML entities. - -Bug fixes: - -* Loofah::XssFoliate was not properly escaping HTML entities when implicitly scrubbing a string attribute. GH #17 - - -== 0.4.3 (2010-01-29) - -Enhancements: - -* All built-in scrubbers are accepted by ActiveRecord::Base.xss_foliate -* Loofah::XssFoliate.xss_foliate_all_models replaces use of the constant LOOFAH_XSS_FOLIATE_ALL_MODELS - -Miscellaneous: - -* Modified documentation for bootstrapping XssFoliate in a Rails app, - since the use of Bundler breaks the previously-documented method. To - be safe, always use an initializer file. - - -== 0.4.2 (2010-01-22) - -Enhancements: - -* Implemented Node#scrub! for scrubbing subtrees. -* Implemented NodeSet#scrub! for scrubbing a set of subtrees. -* Document.text now only serializes <body> contents (ignores <head>) -* <head>, <html> and <body> added to the HTML5lib whitelist. - -Bug fixes: - -* Supporting Rails apps that aren't loading ActiveRecord. GH #10 - -Miscellaneous: - -* Mailing list is now [email protected] / http://librelist.com -* IRC channel is now \#loofah on freenode. - - -== 0.4.1 (2009-11-23) - -Bugfix: - -* Manifest fixed. Whoops. - - -== 0.4.0 (2009-11-21) - -Enhancements: - -* Scrubber class introduced, allowing development of custom scrubbers. -* Added support for XML documents and fragments. -* Added :nofollow HTML scrubber (thanks Luke Melia!) -* Built-in scrubbing methods refactored to use Scrubber. - - - -== 0.3.1 (2009-10-12) - -Bug fixes: - -* Scrubbed Documents properly render html, head and body tags when serialized. - - -== 0.3.0 (2009-10-06) - -Enhancements: - -* New ActiveRecord extension `xss_foliate`, a drop-in replacement for xss_terminate[http://github.com/look/xss_terminate/tree/master]. -* Replacement methods for Rails's helpers, Loofah::Rails.sanitize and Loofah::Rails.strip_tags. -* Official support (and test coverage) for Rails versions 2.3, 2.2, 2.1, 2.0 and 1.2. - -Deprecations: - -* The methods strip_tags, whitewash, whitewash_document, sanitize, and - sanitize_document have been deprecated. See DEPRECATED.rdoc for - details on the equivalent calls with the post-0.2 API. - - -== 0.2.2 (2009-09-30) - -Enhancements: - -* ActiveRecord extension scrubs fields in a before_validation callback - (was previously in a before_save) - - -== 0.2.1 (2009-09-19) - -Enhancements: - -* when loaded in a Rails app, automatically extend ActiveRecord::Base - with html_fragment and html_document. GH #6 (Thanks Josh Nichols!) - -Bugfixes: - -* ActiveRecord scrubbing should generate strings instead of Document or - DocumentFragment objects. GH #5 -* init.rb fixed to support installation as a Rails plugin. GH #6 - (Thanks Josh Nichols!) - - -== 0.2.0 (2009-09-11) - -* Swank new API. -* ActiveRecord extension. -* Uses Nokogiri's Document and DocumentFragment for parsing. -* Updated html5lib codes and tests to revision 1384:b9d3153d7be7. -* Deprecated the Dryopteris sanitization methods. Will be removed in 0.3.0. -* Documentation! Hey! - - -== 0.1.2 (2009-04-30) - -* Added whitewashing -- removal of all attributes and namespaced nodes. You know, for microsofty HTML. - - -== 0.1.0 (2009-02-10) - -* Birthday! diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Gemfile new/Gemfile --- old/Gemfile 2015-08-17 20:10:12.000000000 +0200 +++ new/Gemfile 2017-09-25 03:11:14.000000000 +0200 @@ -5,16 +5,18 @@ source "https://rubygems.org/" gem "nokogiri", ">=1.5.9" +gem "crass", "~>1.0.2" -gem "rdoc", "~>4.0", :group => [:development, :test] gem "rake", ">=0.8", :group => [:development, :test] gem "minitest", "~>2.2", :group => [:development, :test] -gem "rr", "~>1.1.0", :group => [:development, :test] +gem "rr", "~>1.2.0", :group => [:development, :test] gem "json", ">=0", :group => [:development, :test] gem "hoe-gemspec", ">=0", :group => [:development, :test] gem "hoe-debugging", ">=0", :group => [:development, :test] gem "hoe-bundler", ">=0", :group => [:development, :test] gem "hoe-git", ">=0", :group => [:development, :test] -gem "hoe", "~>3.6", :group => [:development, :test] +gem "concourse", ">=0.14.0", :group => [:development, :test] +gem "rdoc", "~>4.0", :group => [:development, :test] +gem "hoe", "~>3.16", :group => [:development, :test] # vim: syntax=ruby diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Manifest.txt new/Manifest.txt --- old/Manifest.txt 2015-08-17 20:10:12.000000000 +0200 +++ new/Manifest.txt 2017-09-25 03:11:14.000000000 +0200 @@ -1,5 +1,5 @@ .gemtest -CHANGELOG.rdoc +CHANGELOG.md Gemfile MIT-LICENSE.txt Manifest.txt diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/README.rdoc new/README.rdoc --- old/README.rdoc 2015-08-17 20:10:12.000000000 +0200 +++ new/README.rdoc 2017-09-25 03:11:14.000000000 +0200 @@ -1,4 +1,4 @@ -= Loofah {<img src="https://travis-ci.org/flavorjones/loofah.png?branch=master" alt="Build Status" />}[https://travis-ci.org/flavorjones/loofah] += Loofah {<img src="https://travis-ci.org/flavorjones/loofah.svg?branch=master" alt="Build Status" />}[https://travis-ci.org/flavorjones/loofah] * https://github.com/flavorjones/loofah * http://rubydoc.info/github/flavorjones/loofah/master/frames diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Rakefile new/Rakefile --- old/Rakefile 2015-08-17 20:10:12.000000000 +0200 +++ new/Rakefile 2017-09-25 03:11:14.000000000 +0200 @@ -1,6 +1,7 @@ require 'rubygems' gem 'hoe', '>= 2.3.0' require 'hoe' +require 'concourse' Hoe.plugin :git Hoe.plugin :gemspec @@ -12,20 +13,22 @@ developer "Bryan Helmkamp", "[email protected]" self.extra_rdoc_files = FileList["*.rdoc"] - self.history_file = "CHANGELOG.rdoc" + self.history_file = "CHANGELOG.md" self.readme_file = "README.rdoc" self.license "MIT" extra_deps << ["nokogiri", ">=1.5.9"] + extra_deps << ["crass", "~> 1.0.2"] extra_dev_deps << ["rake", ">=0.8"] extra_dev_deps << ["minitest", "~>2.2"] - extra_dev_deps << ["rr", "~>1.1.0"] + extra_dev_deps << ["rr", "~>1.2.0"] extra_dev_deps << ["json", ">=0"] extra_dev_deps << ["hoe-gemspec", ">=0"] extra_dev_deps << ["hoe-debugging", ">=0"] extra_dev_deps << ["hoe-bundler", ">=0"] extra_dev_deps << ["hoe-git", ">=0"] + extra_dev_deps << ["concourse", ">=0.14.0"] end task :gemspec do @@ -72,3 +75,5 @@ task :generate_whitelists do load "tasks/generate-whitelists" end + +Concourse.new("loofah").create_tasks! Binary files old/checksums.yaml.gz and new/checksums.yaml.gz differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/loofah/html5/scrub.rb new/lib/loofah/html5/scrub.rb --- old/lib/loofah/html5/scrub.rb 2015-08-17 20:10:12.000000000 +0200 +++ new/lib/loofah/html5/scrub.rb 2017-09-25 03:11:14.000000000 +0200 @@ -1,12 +1,15 @@ #encoding: US-ASCII require 'cgi' +require 'crass' module Loofah module HTML5 # :nodoc: module Scrub CONTROL_CHARACTERS = /[`\u0000-\u0020\u007f\u0080-\u0101]/ + CSS_KEYWORDISH = /\A(#[0-9a-f]+|rgb\(\d+%?,\d*%?,?\d*%?\)?|-?\d{0,2}\.?\d{0,2}(cm|em|ex|in|mm|pc|pt|px|%|,|\))?)\z/ + CRASS_SEMICOLON = {:node => :semicolon, :raw => ";"} class << self @@ -38,6 +41,14 @@ if val_unescaped =~ /^[a-z0-9][-+.a-z0-9]*:/ && ! WhiteList::ALLOWED_PROTOCOLS.include?(val_unescaped.split(WhiteList::PROTOCOL_SEPARATOR)[0]) attr_node.remove next + elsif val_unescaped.split(WhiteList::PROTOCOL_SEPARATOR)[0] == 'data' + # permit only allowed data mediatypes + mediatype = val_unescaped.split(WhiteList::PROTOCOL_SEPARATOR)[1] + mediatype, _ = mediatype.split(';')[0..1] if mediatype + if mediatype && !WhiteList::ALLOWED_URI_DATA_MEDIATYPES.include?(mediatype) + attr_node.remove + next + end end end if WhiteList::SVG_ATTR_VAL_ALLOWS_REF.include?(attr_name) @@ -61,36 +72,35 @@ style.value = scrub_css(style.value) if style end - # lifted nearly verbatim from html5lib def scrub_css style - # disallow urls - style = style.to_s.gsub(/url\s*\(\s*[^\s)]+?\s*\)\s*/, ' ') + style_tree = Crass.parse_properties style + sanitized_tree = [] - # gauntlet - return '' unless style =~ /\A([:,;#%.\sa-zA-Z0-9!]|\w-\w|\'[\s\w]+\'|\"[\s\w]+\"|\([\d,\s]+\))*\z/ - return '' unless style =~ /\A\s*([-\w]+\s*:[^:;]*(;\s*|$))*\z/ - - clean = [] - style.scan(/([-\w]+)\s*:\s*([^:;]*)/) do |prop, val| - next if val.empty? - prop.downcase! - if WhiteList::ALLOWED_CSS_PROPERTIES.include?(prop) - clean << "#{prop}: #{val};" - elsif WhiteList::SHORTHAND_CSS_PROPERTIES.include?(prop.split('-')[0]) - clean << "#{prop}: #{val};" unless val.split().any? do |keyword| - !WhiteList::ALLOWED_CSS_KEYWORDS.include?(keyword) && - keyword !~ /\A(#[0-9a-f]+|rgb\(\d+%?,\d*%?,?\d*%?\)?|-?\d{0,2}\.?\d{0,2}(cm|em|ex|in|mm|pc|pt|px|%|,|\))?)\z/ + style_tree.each do |node| + next unless node[:node] == :property + next if node[:children].any? do |child| + [:url, :bad_url, :function].include? child[:node] + end + name = node[:name].downcase + if WhiteList::ALLOWED_CSS_PROPERTIES.include?(name) || WhiteList::ALLOWED_SVG_PROPERTIES.include?(name) + sanitized_tree << node << CRASS_SEMICOLON + elsif WhiteList::SHORTHAND_CSS_PROPERTIES.include?(name.split('-').first) + value = node[:value].split.map do |keyword| + if WhiteList::ALLOWED_CSS_KEYWORDS.include?(keyword) || keyword =~ CSS_KEYWORDISH + keyword + end + end.compact + unless value.empty? + propstring = sprintf "%s:%s", name, value.join(" ") + sanitized_node = Crass.parse_properties(propstring).first + sanitized_tree << sanitized_node << CRASS_SEMICOLON end - elsif WhiteList::ALLOWED_SVG_PROPERTIES.include?(prop) - clean << "#{prop}: #{val};" end end - style = clean.join(' ') + Crass::Parser.stringify sanitized_tree end - end - end end end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/loofah/html5/whitelist.rb new/lib/loofah/html5/whitelist.rb --- old/lib/loofah/html5/whitelist.rb 2015-08-17 20:10:12.000000000 +0200 +++ new/lib/loofah/html5/whitelist.rb 2017-09-25 03:11:14.000000000 +0200 @@ -145,7 +145,10 @@ PROTOCOL_SEPARATOR = /:|(�*58)|(p)|(�*3a)|(%|%)3A/i ACCEPTABLE_PROTOCOLS = Set.new %w[ed2k ftp http https irc mailto news gopher nntp - telnet webcal xmpp callto feed urn aim rsync tag ssh sftp rtsp afs] + telnet webcal xmpp callto feed urn aim rsync tag ssh sftp rtsp afs data] + + ACCEPTABLE_URI_DATA_MEDIATYPES = Set.new %w[text/plain text/css image/png image/gif + image/jpeg image/svg+xml] # subclasses may define their own versions of these constants ALLOWED_ELEMENTS = ACCEPTABLE_ELEMENTS + MATHML_ELEMENTS + SVG_ELEMENTS @@ -154,6 +157,7 @@ ALLOWED_CSS_KEYWORDS = ACCEPTABLE_CSS_KEYWORDS ALLOWED_SVG_PROPERTIES = ACCEPTABLE_SVG_PROPERTIES ALLOWED_PROTOCOLS = ACCEPTABLE_PROTOCOLS + ALLOWED_URI_DATA_MEDIATYPES = ACCEPTABLE_URI_DATA_MEDIATYPES VOID_ELEMENTS = Set.new %w[ base diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/loofah/scrubber.rb new/lib/loofah/scrubber.rb --- old/lib/loofah/scrubber.rb 2015-08-17 20:10:12.000000000 +0200 +++ new/lib/loofah/scrubber.rb 2017-09-25 03:11:14.000000000 +0200 @@ -86,6 +86,17 @@ raise ScrubberNotFound, "No scrub method has been defined on #{self.class.to_s}" end + # + # If the attribute is not set, add it + # If the attribute is set, don't overwrite the existing value + # + def append_attribute(node, attribute, value) + current_value = node.get_attribute(attribute) || '' + current_values = current_value.split(/\s+/) + updated_value = current_values | [value] + node.set_attribute(attribute, updated_value.join(' ')) + end + private def html5lib_sanitize(node) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/loofah/scrubbers.rb new/lib/loofah/scrubbers.rb --- old/lib/loofah/scrubbers.rb 2015-08-17 20:10:12.000000000 +0200 +++ new/lib/loofah/scrubbers.rb 2017-09-25 03:11:14.000000000 +0200 @@ -59,6 +59,15 @@ # => "ohai! <a href='http://www.myswarmysite.com/' rel="nofollow">I like your blog post</a>" # # + # === Loofah::Scrubbers::NoOpener / scrub!(:noopener) + # + # +:noopener+ adds a rel="noopener" attribute to all links + # + # link_farmers_markup = "ohai! <a href='http://www.myswarmysite.com/'>I like your blog post</a>" + # Loofah.fragment(link_farmers_markup).scrub!(:noopener) + # => "ohai! <a href='http://www.myswarmysite.com/' rel="noopener">I like your blog post</a>" + # + # # === Loofah::Scrubbers::Unprintable / scrub!(:unprintable) # # +:unprintable+ removes unprintable Unicode characters. @@ -192,7 +201,28 @@ def scrub(node) return CONTINUE unless (node.type == Nokogiri::XML::Node::ELEMENT_NODE) && (node.name == 'a') - node.set_attribute('rel', 'nofollow') + append_attribute(node, 'rel', 'nofollow') + return STOP + end + end + + # + # === scrub!(:noopener) + # + # +:noopener+ adds a rel="noopener" attribute to all links + # + # link_farmers_markup = "ohai! <a href='http://www.myswarmysite.com/'>I like your blog post</a>" + # Loofah.fragment(link_farmers_markup).scrub!(:noopener) + # => "ohai! <a href='http://www.myswarmysite.com/' rel="noopener">I like your blog post</a>" + # + class NoOpener < Scrubber + def initialize + @direction = :top_down + end + + def scrub(node) + return CONTINUE unless (node.type == Nokogiri::XML::Node::ELEMENT_NODE) && (node.name == 'a') + append_attribute(node, 'rel', 'noopener') return STOP end end @@ -231,7 +261,7 @@ end def scrub(node) - if node.type == Nokogiri::XML::Node::TEXT_NODE + if node.type == Nokogiri::XML::Node::TEXT_NODE || node.type == Nokogiri::XML::Node::CDATA_SECTION_NODE node.content = node.content.gsub(/\u2028|\u2029/, '') end CONTINUE @@ -247,6 +277,7 @@ :whitewash => Whitewash, :strip => Strip, :nofollow => NoFollow, + :noopener => NoOpener, :newline_block_elements => NewlineBlockElements, :unprintable => Unprintable } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/loofah.rb new/lib/loofah.rb --- old/lib/loofah.rb 2015-08-17 20:10:12.000000000 +0200 +++ new/lib/loofah.rb 2017-09-25 03:11:14.000000000 +0200 @@ -27,7 +27,7 @@ # module Loofah # The version of Loofah you are using - VERSION = '2.0.3' + VERSION = '2.1.1' class << self # Shortcut for Loofah::HTML::Document.parse diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/metadata new/metadata --- old/metadata 2015-08-17 20:10:12.000000000 +0200 +++ new/metadata 2017-09-25 03:11:14.000000000 +0200 @@ -1,7 +1,7 @@ --- !ruby/object:Gem::Specification name: loofah version: !ruby/object:Gem::Version - version: 2.0.3 + version: 2.1.1 platform: ruby authors: - Mike Dalessio @@ -9,7 +9,7 @@ autorequire: bindir: bin cert_chain: [] -date: 2015-08-17 00:00:00.000000000 Z +date: 2017-09-25 00:00:00.000000000 Z dependencies: - !ruby/object:Gem::Dependency name: nokogiri @@ -26,19 +26,19 @@ - !ruby/object:Gem::Version version: 1.5.9 - !ruby/object:Gem::Dependency - name: rdoc + name: crass requirement: !ruby/object:Gem::Requirement requirements: - - "~>" - !ruby/object:Gem::Version - version: '4.0' - type: :development + version: 1.0.2 + type: :runtime prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - "~>" - !ruby/object:Gem::Version - version: '4.0' + version: 1.0.2 - !ruby/object:Gem::Dependency name: rake requirement: !ruby/object:Gem::Requirement @@ -73,14 +73,14 @@ requirements: - - "~>" - !ruby/object:Gem::Version - version: 1.1.0 + version: 1.2.0 type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - "~>" - !ruby/object:Gem::Version - version: 1.1.0 + version: 1.2.0 - !ruby/object:Gem::Dependency name: json requirement: !ruby/object:Gem::Requirement @@ -152,19 +152,47 @@ - !ruby/object:Gem::Version version: '0' - !ruby/object:Gem::Dependency + name: concourse + requirement: !ruby/object:Gem::Requirement + requirements: + - - ">=" + - !ruby/object:Gem::Version + version: 0.14.0 + type: :development + prerelease: false + version_requirements: !ruby/object:Gem::Requirement + requirements: + - - ">=" + - !ruby/object:Gem::Version + version: 0.14.0 +- !ruby/object:Gem::Dependency + name: rdoc + requirement: !ruby/object:Gem::Requirement + requirements: + - - "~>" + - !ruby/object:Gem::Version + version: '4.0' + type: :development + prerelease: false + version_requirements: !ruby/object:Gem::Requirement + requirements: + - - "~>" + - !ruby/object:Gem::Version + version: '4.0' +- !ruby/object:Gem::Dependency name: hoe requirement: !ruby/object:Gem::Requirement requirements: - - "~>" - !ruby/object:Gem::Version - version: '3.13' + version: '3.16' type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement requirements: - - "~>" - !ruby/object:Gem::Version - version: '3.13' + version: '3.16' description: |- Loofah is a general library for manipulating and transforming HTML/XML documents and fragments. It's built on top of Nokogiri and libxml2, so @@ -184,13 +212,13 @@ executables: [] extensions: [] extra_rdoc_files: -- CHANGELOG.rdoc +- CHANGELOG.md - MIT-LICENSE.txt - Manifest.txt - README.rdoc files: - ".gemtest" -- CHANGELOG.rdoc +- CHANGELOG.md - Gemfile - MIT-LICENSE.txt - Manifest.txt @@ -248,7 +276,7 @@ version: '0' requirements: [] rubyforge_project: -rubygems_version: 2.4.6 +rubygems_version: 2.6.12 signing_key: specification_version: 4 summary: Loofah is a general library for manipulating and transforming HTML/XML documents diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/test/assets/testdata_sanitizer_tests1.dat new/test/assets/testdata_sanitizer_tests1.dat --- old/test/assets/testdata_sanitizer_tests1.dat 2015-08-17 20:10:12.000000000 +0200 +++ new/test/assets/testdata_sanitizer_tests1.dat 2017-09-25 03:11:14.000000000 +0200 @@ -152,7 +152,7 @@ { "name": "platypus", "input": "<a href=\"http://www.ragingplatypus.com/\" style=\"display:block; position:absolute; left:0; top:0; width:100%; height:100%; z-index:1; background-color:black; background-image:url(http://www.ragingplatypus.com/i/cam-full.jpg); background-x:center; background-y:center; background-repeat:repeat;\">never trust your upstream platypus</a>", - "output": "<a href='http://www.ragingplatypus.com/' style='display: block; width: 100%; height: 100%; background-color: black; background-x: center; background-y: center;'>never trust your upstream platypus</a>" + "output": "<a href='http://www.ragingplatypus.com/' style='display:block;width:100%;height:100%;background-color:black;background-x:center;background-y:center;'>never trust your upstream platypus</a>" }, { @@ -345,6 +345,7 @@ "name": "should_sanitize_script_tag_with_multiple_open_brackets", "input": "<<script>alert(\"XSS\");//<</script>", "output": "alert(\"XSS\");//", + "xhtml": "<<script>alert('XSS');//<</script>", "rexml": "Ill-formed XHTML!" }, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/test/html5/test_sanitizer.rb new/test/html5/test_sanitizer.rb --- old/test/html5/test_sanitizer.rb 2015-08-17 20:10:12.000000000 +0200 +++ new/test/html5/test_sanitizer.rb 2017-09-25 03:11:14.000000000 +0200 @@ -34,7 +34,7 @@ def assert_completes_in_reasonable_time &block t0 = Time.now block.call - assert_in_delta t0, Time.now, 0.01 # arbitrary seconds + assert_in_delta t0, Time.now, 0.1 # arbitrary seconds end (HTML5::WhiteList::ALLOWED_ELEMENTS).each do |tag_name| @@ -136,6 +136,41 @@ check_sanitization(input, output, output, output) end end + + HTML5::WhiteList::ALLOWED_URI_DATA_MEDIATYPES.each do |data_uri_type| + define_method "test_should_allow_data_#{data_uri_type}_uris" do + input = %(<a href="data:#{data_uri_type}">foo</a>) + output = "<a href='data:#{data_uri_type}'>foo</a>" + check_sanitization(input, output, output, output) + + input = %(<a href="data:#{data_uri_type};base64,R0lGODlhAQABA">foo</a>) + output = "<a href='data:#{data_uri_type};base64,R0lGODlhAQABA'>foo</a>" + check_sanitization(input, output, output, output) + end + end + + HTML5::WhiteList::ALLOWED_URI_DATA_MEDIATYPES.each do |data_uri_type| + define_method "test_should_allow_uppercase_data_#{data_uri_type}_uris" do + input = %(<a href="DATA:#{data_uri_type.upcase}">foo</a>) + output = "<a href='DATA:#{data_uri_type.upcase}'>foo</a>" + check_sanitization(input, output, output, output) + end + end + + def test_should_disallow_other_uri_mediatypes + input = %(<a href="data:foo">foo</a>) + output = "<a>foo</a>" + check_sanitization(input, output, output, output) + + input = %(<a href="data:image/xxx">foo</a>) + output = "<a>foo</a>" + check_sanitization(input, output, output, output) + + input = %(<a href="data:image/xxx;base64,R0lGODlhAQABA">foo</a>) + output = "<a>foo</a>" + check_sanitization(input, output, output, output) + end + HTML5::WhiteList::SVG_ALLOW_LOCAL_HREF.each do |tag_name| next unless HTML5::WhiteList::ALLOWED_ELEMENTS.include?(tag_name) @@ -229,26 +264,51 @@ end def test_css_negative_value_sanitization - skip "pending better CSS parsing, see https://github.com/flavorjones/loofah/issues/90" html = "<span style=\"letter-spacing:-0.03em;\">" sane = Nokogiri::HTML(Loofah.scrub_fragment(html, :escape).to_xml) assert_match %r/-0.03em/, sane.inner_html end def test_css_negative_value_sanitization_shorthand_css_properties - skip "pending better CSS parsing, see https://github.com/flavorjones/loofah/issues/90" html = "<span style=\"margin-left:-0.05em;\">" sane = Nokogiri::HTML(Loofah.scrub_fragment(html, :escape).to_xml) assert_match %r/-0.05em/, sane.inner_html end def test_issue_90_slow_regex + skip("timing tests are hard to make pass and have little regression-testing value") + html = %q{<span style="background: url('data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2232%22%20height%3D%2232%22%20viewBox%3D%220%200%2032%2032%22%3E%3Cpath%20fill%3D%22%23D4C8AE%22%20d%3D%22M0%200h32v32h-32z%22%2F%3E%3Cpath%20fill%3D%22%2383604B%22%20d%3D%22M0%200h31.99v11.75h-31.99z%22%2F%3E%3Cpath%20fill%3D%22%233D2319%22%20d%3D%22M0%2011.5h32v.5h-32z%22%2F%3E%3Cpath%20fill%3D%22%23F83651%22%20d%3D%22M5%200h1v10.5h-1z%22%2F%3E%3Cpath%20fill%3D%22%23FCD050%22%20d%3D%22M6%200h1v10.5h-1z%22%2F%3E%3Cpath%20fill%3D%22%2371C797%22%20d%3D%22M7%200h1v10.5h-1z%22%2F%3E%3Cpath%20fill%3D%22%23509CF9%22%20d%3D%22M8%200h1v10.5h-1z%22%2F%3E%3ClinearGradient%20id%3D%22a%22%20gradientUnits%3D%22userSpaceOnUse%22%20x1%3D%2224.996%22%20y1%3D%2210.5%22%20x2%3D%2224.996%22%20y2%3D%224.5%22%3E%3Cstop%20offset%3D%220%22%20stop-color%3D%22%23796055%22%2F%3E%3Cstop%20offset%3D%22.434%22%20stop-color%3D%22%23614C43%22%2F%3E%3Cstop%20offset%3D%221%22%20stop-color%3D%22%233D2D28%22%2F%3E%3C%2FlinearGradient%3E%3Cpath%20fill%3D%22url(%23a)%22%20d%3D%22M28%208.5c0%201.1-.9%202-2%202h-2c-1.1%200-2-.9-2-2v-2c0-1.1.9-2%202-2h2c1.1%200%202%20.9%202%202v2z%22%2F%3E%3Cpath%20fill%3D%22%235F402E%22%20d%3D%22M28%208c0%201.1-.9%202-2%202h-2c-1.1%200-2-.9-2-2v-2c0-1.1.9-2%202-2h2c1.1%200%202%20.9%202%202v2z%22%2F%3E%3C');"></span>} assert_completes_in_reasonable_time { - sane = Nokogiri::HTML(Loofah.scrub_fragment(html, :strip).to_html) + Nokogiri::HTML(Loofah.scrub_fragment(html, :strip).to_html) } end + + def test_upper_case_css_property + html = "<div style=\"COLOR: BLUE; NOTAPROPERTY: RED;\">asdf</div>" + sane = Nokogiri::HTML(Loofah.scrub_fragment(html, :strip).to_xml) + assert_match(/COLOR:\s*BLUE/i, sane.at_css("div")["style"]) + refute_match(/NOTAPROPERTY/i, sane.at_css("div")["style"]) + end + + def test_many_properties_some_allowed + html = "<div style=\"background: bold notaproperty center alsonotaproperty 10px;\">asdf</div>" + sane = Nokogiri::HTML(Loofah.scrub_fragment(html, :strip).to_xml) + assert_match(/bold\s+center\s+10px/, sane.at_css("div")["style"]) + end + + def test_many_properties_non_allowed + html = "<div style=\"background: notaproperty alsonotaproperty;\">asdf</div>" + sane = Nokogiri::HTML(Loofah.scrub_fragment(html, :strip).to_xml) + assert_nil sane.at_css("div")["style"] + end + + def test_svg_properties + html = "<line style='stroke-width: 10px;'></line>" + sane = Nokogiri::HTML(Loofah.scrub_fragment(html, :strip).to_xml) + assert_match(/stroke-width:\s*10px/, sane.at_css("line")["style"]) + end end # <html5_license> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/test/integration/test_helpers.rb new/test/integration/test_helpers.rb --- old/test/integration/test_helpers.rb 2015-08-17 20:10:12.000000000 +0200 +++ new/test/integration/test_helpers.rb 2017-09-25 03:11:14.000000000 +0200 @@ -37,7 +37,7 @@ context ".sanitize_css" do it "removes unsafe css properties" do - assert_equal "display: block; background-color: blue;", Loofah::Helpers.sanitize_css("display:block;background-image:url(http://www.ragingplatypus.com/i/cam-full.jpg);background-color:blue") + assert_match(/display:\s*block;\s*background-color:\s*blue;/, Loofah::Helpers.sanitize_css("display:block;background-image:url(http://www.ragingplatypus.com/i/cam-full.jpg);background-color:blue")) end end end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/test/integration/test_scrubbers.rb new/test/integration/test_scrubbers.rb --- old/test/integration/test_scrubbers.rb 2015-08-17 20:10:12.000000000 +0200 +++ new/test/integration/test_scrubbers.rb 2017-09-25 03:11:14.000000000 +0200 @@ -13,8 +13,17 @@ NOFOLLOW_FRAGMENT = '<a href="http://www.example.com/">Click here</a>' NOFOLLOW_RESULT = '<a href="http://www.example.com/" rel="nofollow">Click here</a>' - UNPRINTABLE_FRAGMENT = "<b>Lo\u2029ofah ro\u2028cks!</b>" - UNPRINTABLE_RESULT = "<b>Loofah rocks!</b>" + NOFOLLOW_WITH_REL_FRAGMENT = '<a href="http://www.example.com/" rel="noopener">Click here</a>' + NOFOLLOW_WITH_REL_RESULT = '<a href="http://www.example.com/" rel="noopener nofollow">Click here</a>' + + NOOPENER_FRAGMENT = '<a href="http://www.example.com/">Click here</a>' + NOOPENER_RESULT = '<a href="http://www.example.com/" rel="noopener">Click here</a>' + + NOOPENER_WITH_REL_FRAGMENT = '<a href="http://www.example.com/" rel="nofollow">Click here</a>' + NOOPENER_WITH_REL_RESULT = '<a href="http://www.example.com/" rel="nofollow noopener">Click here</a>' + + UNPRINTABLE_FRAGMENT = "<b>Lo\u2029ofah ro\u2028cks!</b><script>x\u2028y</script>" + UNPRINTABLE_RESULT = "<b>Loofah rocks!</b><script>xy</script>" ENTITY_FRAGMENT = "<p>this is < that "&" the other > boo'ya</p><div>w00t</div>" ENTITY_TEXT = %Q(this is < that "&" the other > boo\'yaw00t) @@ -244,12 +253,49 @@ end context ":nofollow" do - it "add a 'nofollow' attribute to hyperlinks" do - doc = Loofah::HTML::DocumentFragment.parse "<div>#{NOFOLLOW_FRAGMENT}</div>" - result = doc.scrub! :nofollow - assert_equal NOFOLLOW_RESULT, doc.xpath("./div").inner_html - assert_equal doc, result + context "for a hyperlink that does not have a rel attribute" do + it "add a 'nofollow' attribute to hyperlinks" do + doc = Loofah::HTML::DocumentFragment.parse "<div>#{NOFOLLOW_FRAGMENT}</div>" + result = doc.scrub! :nofollow + + assert_equal NOFOLLOW_RESULT, doc.xpath("./div").inner_html + assert_equal doc, result + end + end + + context "for a hyperlink that does have a rel attribute" do + it "appends nofollow to rel attribute" do + doc = Loofah::HTML::DocumentFragment.parse "<div>#{NOFOLLOW_WITH_REL_FRAGMENT}</div>" + result = doc.scrub! :nofollow + + assert_equal NOFOLLOW_WITH_REL_RESULT, doc.xpath("./div").inner_html + assert_equal doc, result + end + end + + + end + + context ":noopener" do + context "for a hyperlink without a 'rel' attribute" do + it "add a 'noopener' attribute to hyperlinks" do + doc = Loofah::HTML::DocumentFragment.parse "<div>#{NOOPENER_FRAGMENT}</div>" + result = doc.scrub! :noopener + + assert_equal NOOPENER_RESULT, doc.xpath("./div").inner_html + assert_equal doc, result + end + end + + context "for a hyperlink that does have a rel attribute" do + it "appends 'noopener' to 'rel' attribute" do + doc = Loofah::HTML::DocumentFragment.parse "<div>#{NOOPENER_WITH_REL_FRAGMENT}</div>" + result = doc.scrub! :noopener + + assert_equal NOOPENER_WITH_REL_RESULT, doc.xpath("./div").inner_html + assert_equal doc, result + end end end
