pax_global_header 0000666 0000000 0000000 00000000064 13576734765 0014541 g ustar 00root root 0000000 0000000 52 comment=a363d620eba0076479faad86f0cf85a56b2b3c0a html-pipeline-2.12.3/ 0000775 0000000 0000000 00000000000 13576734765 0014375 5 ustar 00root root 0000000 0000000 html-pipeline-2.12.3/.gitignore 0000664 0000000 0000000 00000000274 13576734765 0016370 0 ustar 00root root 0000000 0000000 *.gem *.rbc .bundle .config .yardoc Gemfile.lock gemfiles/*.lock InstalledFiles _yardoc coverage doc/ lib/bundler/man pkg rdoc spec/reports test/tmp test/version_tmp tmp exec/* vendor/gems html-pipeline-2.12.3/.travis.yml 0000664 0000000 0000000 00000001431 13576734765 0016505 0 ustar 00root root 0000000 0000000 language: ruby cache: bundler bundler_args: --path ../../vendor/bundle addons: apt: sources: - libicu-dev - kalakris-cmake packages: - cmake script: bundle exec rake gemfile: - gemfiles/rails_6.gemfile - gemfiles/rails_5.gemfile - gemfiles/rails_4.gemfile - gemfiles/rails_3.gemfile rvm: - 2.4.6 - 2.3.8 - 2.5.7 - ruby-head matrix: fast_finish: true allow_failures: - rvm: ruby-head exclude: - gemfile: gemfiles/rails_6.gemfile rvm: 2.4.6 - gemfile: gemfiles/rails_6.gemfile rvm: 2.3.8 - gemfile: gemfiles/rails_4.gemfile rvm: 2.5.7 - gemfile: gemfiles/rails_4.gemfile rvm: 2.4.6 - gemfile: gemfiles/rails_3.gemfile rvm: 2.5.7 - gemfile: gemfiles/rails_3.gemfile rvm: 2.4.6 html-pipeline-2.12.3/Appraisals 0000664 0000000 0000000 00000000432 13576734765 0016416 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true appraise 'rails-3' do gem 'rack', '< 2' gem 'rails', '3.2.22.2' end appraise 'rails-4' do gem 'rack', '< 2' gem 'rails', '~> 4.2.6' end appraise 'rails-5' do gem 'rails', '~> 5.0.0' end appraise 'rails-6' do gem 'rails', '~> 6.0.0' end html-pipeline-2.12.3/CHANGELOG.md 0000664 0000000 0000000 00000023266 13576734765 0016217 0 ustar 00root root 0000000 0000000 # CHANGELOG ## 2.12.0 * Team mention filter [#314](https://github.com/jch/html-pipeline/pull/314) ## 2.11.1 * Avoid YARD warning: Unknown tag @mention [#309](https://github.com/jch/html-pipeline/pull/309) * Freeze string literals in Ruby 2.3 and beyond [#313](https://github.com/jch/html-pipeline/pull/313) ## 2.11.0 * Test against Ruby 2.4 [#310](https://github.com/jch/html-pipeline/pull/310) * CamoFilter: use String#unpack to hexencode URLs [#256](https://github.com/jch/html-pipeline/pull/256) ## 2.10.0 * Add XMPP URI [#307](https://github.com/jch/html-pipeline/pull/307) * Stop testing against Ruby 2.2 ## 2.9.2 * Whitelist various inline semantic/formatting tags [#306](https://github.com/jch/html-pipeline/pull/306) ## 2.9.1 * Render irc and ircs URLs [#191](https://github.com/jch/html-pipeline/pull/191) ## 2.9.0 * Fix one more missing freeze [#300](https://github.com/jch/html-pipeline/pull/300) * Adds `UNSAFE` option to CommonMarker usage where needed [#304](https://github.com/jch/html-pipeline/pull/304) ## 2.8.4 * Freeze all elements in HTML::Pipeline::SanitizationFilter [#299](https://github.com/jch/html-pipeline/pull/299) ## 2.8.3 * Whitelist some accessibility properties [#298](https://github.com/jch/html-pipeline/pull/298) ## 2.8.2 * Update ruby-sanitize (fixes CVE-2018-3740) ## 2.8.1 * Fix XSS vulnerability on table of content generation [#296](https://github.com/jch/html-pipeline/pull/296) ## 2.8.0 * Ensure `
` nodes are not removed after syntax highlighting [#295](https://github.com/jch/html-pipeline/pull/295) ## 2.7.2 * Apply mention filter & emoji filter on node text [#290](https://github.com/jch/html-pipeline/pull/290) * Disable processing @mentions in `' results = MarkdownFilter.new(script, unsafe: true, commonmarker_extensions: extensions).call assert_equal results, script end def test_legitimate_custom_renderer_without_tagfilter extensions = HTML::Pipeline::MarkdownFilter::DEFAULT_COMMONMARKER_EXTENSIONS - [:tagfilter] script = '' results = MarkdownFilter.new(script, unsafe: true, commonmarker_extensions: extensions, commonmarker_renderer: CustomRenderer).call assert_equal results, script end end class GFMTest < Minitest::Test def gfm(text) MarkdownFilter.call(text, gfm: true, unsafe: true) end def test_not_touch_single_underscores_inside_words assert_equal 'foo_bar
', gfm('foo_bar') end def test_not_touch_underscores_in_code_blocks assert_equal "", gfm(' foo_bar_baz') end def test_not_touch_underscores_in_pre_blocks assert_equal "foo_bar_baz\n
\nfoo_bar_baz\n", gfm("\nfoo_bar_baz\n") end def test_not_touch_two_or_more_underscores_inside_words assert_equal 'foo_bar_baz
', gfm('foo_bar_baz') end def test_turn_newlines_into_br_tags_in_simple_cases assert_equal "foo
", gfm("foo\nbar") end def test_convert_newlines_in_all_groups assert_equal "
\nbarapple
\n" \ "
\npear
\norangeruby
", gfm("apple\npear\norange\n\nruby\npython\nerlang") end def test_convert_newlines_in_even_long_groups assert_equal "
\npython
\nerlangapple
\n" \ "
\npear
\norange
\nbananaruby
", gfm("apple\npear\norange\nbanana\n\nruby\npython\nerlang") end def test_not_convert_newlines_in_lists assert_equal "
\npython
\nerlangfoo
\nbar
", gfm("# foo\n# bar") assert_equal "
@kneath: check it out.
' doc = Nokogiri::HTML::DocumentFragment.parse(body) res = filter(doc, '/') assert_same doc, res link = '@kneath' assert_equal "#{link}: check it out.
", res.to_html end def test_filtering_plain_text body = '@kneath: check it out.
' res = filter(body, '/') link = '@kneath' assert_equal "#{link}: check it out.
", res.to_html end def test_not_replacing_mentions_in_pre_tags body = '@kneath: okay' assert_equal body, filter(body).to_html end def test_not_replacing_mentions_in_code_tags body = '
@kneath:
okay
@kneath okay
' assert_equal body, filter(body).to_html end def test_entity_encoding_and_whatnot body = "@kneath what's up
" link = '@kneath' assert_equal "#{link} what's up
", filter(body, '/').to_html end def test_html_injection body = '@kneath <script>alert(0)</script>
' link = '@kneath' assert_equal "#{link} <script>alert(0)</script>
", filter(body, '/').to_html end def test_links_to_nothing_when_no_info_url_given body = 'How do I @mention someone?
' assert_equal 'How do I @mention someone?
', filter(body, '/').to_html end def test_links_to_more_info_when_info_url_given body = 'How do I @mention someone?
' link = '@mention' assert_equal "How do I #{link} someone?
", filter(body, '/', 'https://github.com/blog/821').to_html end def test_base_url_slash body = 'Hi, @jch!
' link = '@jch' assert_equal "Hi, #{link}!
", filter(body, '/').to_html end def test_base_url_under_custom_route body = 'Hi, @jch!
' link = '@jch' assert_equal "Hi, #{link}!
", filter(body, '/userprofile').to_html end def test_base_url_slash_with_tilde body = 'Hi, @jch!
' link = '@jch' assert_equal "Hi, #{link}!
", filter(body, '/~').to_html end MarkdownPipeline = HTML::Pipeline.new [ HTML::Pipeline::MarkdownFilter, HTML::Pipeline::MentionFilter ] def mentioned_usernames result = {} MarkdownPipeline.call(@body, {}, result) result[:mentioned_usernames] end def test_matches_usernames_in_body @body = '@test how are you?' assert_equal %w[test], mentioned_usernames end def test_matches_usernames_with_dashes @body = 'hi @some-user' assert_equal %w[some-user], mentioned_usernames end def test_matches_usernames_followed_by_a_single_dot @body = 'okay @some-user.' assert_equal %w[some-user], mentioned_usernames end def test_matches_usernames_followed_by_multiple_dots @body = 'okay @some-user...' assert_equal %w[some-user], mentioned_usernames end def test_does_not_match_email_addresses @body = 'aman@tmm1.net' assert_equal [], mentioned_usernames end def test_does_not_match_domain_name_looking_things @body = 'we need a @github.com email' assert_equal [], mentioned_usernames end def test_does_not_match_organization_team_mentions @body = 'we need to @github/enterprise know' assert_equal [], mentioned_usernames end def test_matches_colon_suffixed_names @body = '@tmm1: what do you think?' assert_equal %w[tmm1], mentioned_usernames end def test_matches_list_of_names @body = '@defunkt @atmos @kneath' assert_equal %w[defunkt atmos kneath], mentioned_usernames end def test_matches_list_of_names_with_commas @body = '/cc @defunkt, @atmos, @kneath' assert_equal %w[defunkt atmos kneath], mentioned_usernames end def test_matches_inside_brackets @body = '(@mislav) and [@rtomayko]' assert_equal %w[mislav rtomayko], mentioned_usernames end def test_doesnt_ignore_invalid_users @body = '@defunkt @mojombo and @somedude' assert_equal %w[defunkt mojombo somedude], mentioned_usernames end def test_returns_distinct_set @body = '/cc @defunkt, @atmos, @kneath, @defunkt, @defunkt' assert_equal %w[defunkt atmos kneath], mentioned_usernames end def test_does_not_match_inline_code_block_with_multiple_code_blocks @body = "something\n\n`/cc @defunkt @atmos @kneath` `/cc @atmos/atmos`" assert_equal %w[], mentioned_usernames end def test_mention_at_end_of_parenthetical_sentence @body = "(We're talking 'bout @ymendel.)" assert_equal %w[ymendel], mentioned_usernames end def test_username_pattern_can_be_customized body = '@_abc: test.
' doc = Nokogiri::HTML::DocumentFragment.parse(body) res = filter(doc, '/', nil, /(_[a-z]{3})/) link = '@_abc' assert_equal "#{link}: test.
", res.to_html end def test_filter_does_not_create_a_new_object_for_default_username_pattern body = 'heyo
' doc = Nokogiri::HTML::DocumentFragment.parse(body) assert_raises(TypeError) { PlainTextInputFilter.call(doc, {}) } end def test_wraps_input_in_a_div_element doc = PlainTextInputFilter.call('howdy pahtner', {}) assert_equal 'YO DAWG
) html = SanitizationFilter.call(orig).to_s refute_match /font-size/, html refute_match /style/, html end def test_removing_script_event_handler_attributes orig = %(YO DAWG) html = SanitizationFilter.call(orig).to_s refute_match /javscript/, html refute_match /onclick/, html end def test_sanitizes_li_elements_not_contained_in_ul_or_ol stuff = "a\nColumn 1 |
---|
Sum |
1 |
hello', highlight: 'coffeescript' doc = filter.call assert !doc.css('.highlight').empty? assert !doc.css('.highlight-coffeescript').empty? end def test_highlight_default_will_not_override filter = SyntaxHighlightFilter.new \ "
hello
", highlight: 'coffeescript'
doc = filter.call
assert doc.css('.highlight-coffeescript').empty?
assert !doc.css('.highlight-c').empty?
end
def test_highlight_does_not_remove_pre_tag
filter = SyntaxHighlightFilter.new \
"hello
", highlight: 'coffeescript'
doc = filter.call
assert !doc.css('pre').empty?
end
def test_highlight_allows_optional_scope
filter = SyntaxHighlightFilter.new \
"hello
", highlight: 'coffeescript', scope: 'test-scope'
doc = filter.call
assert !doc.css('pre.test-scope').empty?
end
def test_highlight_keeps_the_pre_tags_lang
filter = SyntaxHighlightFilter.new \
"hello
", highlight: 'coffeescript'
doc = filter.call
assert !doc.css('pre[lang=c]').empty?
end
def test_highlight_handles_nested_pre_tags
inner_code = "console.log('i am nested!')" escaped = EscapeUtils.escape_html(inner_code) html = "
#{escaped}
"
filter = SyntaxHighlightFilter.new html, highlight: 'html'
doc = filter.call
assert_equal 2, doc.css('span[class=nt]').length
assert_equal EscapeUtils.unescape_html(escaped), doc.inner_text
end
end
html-pipeline-2.12.3/test/html/pipeline/team_mention_filter_test.rb 0000664 0000000 0000000 00000014171 13576734765 0025541 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require 'test_helper'
class HTML::Pipeline::TeamMentionFilterTest < Minitest::Test
def filter(html, base_url = '/', team_pattern = nil)
HTML::Pipeline::TeamMentionFilter.call(html, base_url: base_url, team_pattern: team_pattern)
end
def test_filtering_plain_text
body = '@github/team: check it out.
' res = filter(body, '/') link = '@github/team' assert_equal "#{link}: check it out.
", res.to_html end def test_filtering_a_documentfragment body = '@github/team: check it out.
' doc = Nokogiri::HTML::DocumentFragment.parse(body) res = filter(doc, '/') assert_same doc, res link = '@github/team' assert_equal "#{link}: check it out.
", res.to_html end def test_not_replacing_mentions_in_pre_tags body = '@github/team: okay' assert_equal body, filter(body).to_html end def test_not_replacing_mentions_in_code_tags body = '
@github/team:
okay
@github/team okay
' assert_equal body, filter(body).to_html end def test_entity_encoding_and_whatnot body = "@github/team what's up
" link = '@github/team' assert_equal "#{link} what's up
", filter(body, '/').to_html end def test_html_injection body = '@github/team <script>alert(0)</script>
' link = '@github/team' assert_equal "#{link} <script>alert(0)</script>
", filter(body, '/').to_html end def test_links_to_nothing_with_user_mention body = 'Hi, @kneath
' assert_equal 'Hi, @kneath
', filter(body, '/').to_html end def test_base_url_slash body = 'Hi, @github/team!
' link = '@github/team' assert_equal "Hi, #{link}!
", filter(body, '/').to_html end def test_base_url_under_custom_route body = 'Hi, @org/team!
' link = '@org/team' assert_equal "Hi, #{link}!
", filter(body, 'www.github.com').to_html end def test_base_url_slash_with_tilde body = 'Hi, @github/team!
' link = '@github/team' assert_equal "Hi, #{link}!
", filter(body, '/~').to_html end def test_multiple_team_mentions body = 'Hi, @github/whale and @github/donut!
' link_whale = '@github/whale' link_donut = '@github/donut' assert_equal "Hi, #{link_whale} and #{link_donut}!
", filter(body).to_html end MarkdownPipeline = HTML::Pipeline.new [ HTML::Pipeline::MarkdownFilter, HTML::Pipeline::TeamMentionFilter ] def mentioned_teams result = {} MarkdownPipeline.call(@body, {}, result) result[:mentioned_teams] end def test_matches_teams_in_body @body = '@test/team how are you?' assert_equal %w[team], mentioned_teams end def test_matches_orgs_with_dashes @body = 'hi @some-org/team' assert_equal %w[team], mentioned_teams end def test_matches_teams_with_dashes @body = 'hi @github/some-team' assert_equal %w[some-team], mentioned_teams end def test_matches_teams_followed_by_a_single_dot @body = 'okay @github/team.' assert_equal %w[team], mentioned_teams end def test_matches_teams_followed_by_multiple_dots @body = 'okay @github/team...' assert_equal %w[team], mentioned_teams end def test_does_not_match_email_addresses @body = 'aman@tmm1.net' assert_equal [], mentioned_teams end def test_does_not_match_domain_name_looking_things @body = 'we need a @github.com email' assert_equal [], mentioned_teams end def test_does_not_match_user_mentions @body = 'we need to @enterprise know' assert_equal [], mentioned_teams end def test_matches_colon_suffixed_team_names @body = '@github/team: what do you think?' assert_equal %w[team], mentioned_teams end def test_matches_list_of_teams @body = '@github/whale @github/donut @github/green' assert_equal %w[whale donut green], mentioned_teams end def test_matches_list_of_teams_with_commas @body = '/cc @github/whale, @github/donut, @github/green' assert_equal %w[whale donut green], mentioned_teams end def test_matches_inside_brackets @body = '(@github/whale) and [@github/donut]' assert_equal %w[whale donut], mentioned_teams end def test_returns_distinct_set @body = '/cc @github/whale, @github/donut, @github/whale, @github/whale' assert_equal %w[whale donut], mentioned_teams end def test_does_not_match_inline_code_block_with_multiple_code_blocks @body = "something\n\n`/cc @github/whale @github/donut @github/green` `/cc @donut/donut`" assert_equal %w[], mentioned_teams end def test_mention_at_end_of_parenthetical_sentence @body = "(We're talking 'bout @some-org/some-team.)" assert_equal %w[some-team], mentioned_teams end def test_team_pattern_can_be_customized body = '@_abc/XYZ: test
' doc = Nokogiri::HTML::DocumentFragment.parse(body) res = filter(doc, '/', /@(_[a-z]{3})\/([A-Z]{3})/) link = '@_abc/XYZ' assert_equal "#{link}: test
", res.to_html end def test_mention_link_filter filter = HTML::Pipeline::TeamMentionFilter.new nil expected = "@bot/hubot" assert_equal expected, filter.mention_link_filter('@bot/hubot') end end html-pipeline-2.12.3/test/html/pipeline/toc_filter_test.rb 0000664 0000000 0000000 00000012343 13576734765 0023646 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true require 'test_helper' class HTML::Pipeline::TableOfContentsFilterTest < Minitest::Test TocFilter = HTML::Pipeline::TableOfContentsFilter TocPipeline = HTML::Pipeline.new [ HTML::Pipeline::TableOfContentsFilter ] def toc result = {} TocPipeline.call(@orig, {}, result) result[:toc] end def test_anchors_are_added_properly orig = %(Will swarm on any motherfucker in a blue uniform
) assert_includes TocFilter.call(orig).to_s, 'Ice cubeWill swarm on any motherfucker in a blue uniform
) assert_includes toc, %(