diff --git a/Rakefile b/Rakefile
index 343704e8a..0ea6c54b3 100644
--- a/Rakefile
+++ b/Rakefile
@@ -231,7 +231,7 @@ end
task :stdlib_test => :compile do
test_files = FileList["test/stdlib/**/*_test.rb"].reject do |path|
- path =~ %r{Ractor} || path =~ %r{Encoding} || path =~ %r{CGI_test}
+ path =~ %r{Ractor} || path =~ %r{Encoding} || path =~ %r{CGI-escape_test}
end
if ENV["RANDOMIZE_STDLIB_TEST_ORDER"] == "true"
@@ -240,7 +240,7 @@ task :stdlib_test => :compile do
sh "#{ruby} -Ilib #{bin}/test_runner.rb #{test_files.join(' ')}"
# TODO: Ractor tests need to be run in a separate process
- sh "#{ruby} -Ilib #{bin}/test_runner.rb test/stdlib/CGI_test.rb"
+ sh "#{ruby} -Ilib #{bin}/test_runner.rb test/stdlib/CGI-escape_test.rb"
sh "#{ruby} -Ilib #{bin}/test_runner.rb test/stdlib/Ractor_test.rb"
sh "#{ruby} -Ilib #{bin}/test_runner.rb test/stdlib/Encoding_test.rb"
end
diff --git a/lib/rbs/collection/config/lockfile_generator.rb b/lib/rbs/collection/config/lockfile_generator.rb
index 4dcfbc460..56e04497f 100644
--- a/lib/rbs/collection/config/lockfile_generator.rb
+++ b/lib/rbs/collection/config/lockfile_generator.rb
@@ -14,6 +14,7 @@ class LockfileGenerator
"net-smtp" => nil,
"nkf" => nil,
"observer" => nil,
+ "cgi" => nil,
}
class GemfileLockMismatchError < StandardError
diff --git a/stdlib/cgi-escape/0/escape.rbs b/stdlib/cgi-escape/0/escape.rbs
new file mode 100644
index 000000000..45baa4da1
--- /dev/null
+++ b/stdlib/cgi-escape/0/escape.rbs
@@ -0,0 +1,153 @@
+#
+# :stopdoc
+#
+class CGI
+ include Escape
+
+ extend Escape
+
+ #
+ # Escape/unescape for CGI, HTML, URI.
+ #
+ module Escape
+ #
+ # URL-encode a string into application/x-www-form-urlencoded. Space characters
+ # (+" "+) are encoded with plus signs (+"+"+)
+ # url_encoded_string = CGI.escape("'Stop!' said Fred")
+ # # => "%27Stop%21%27+said+Fred"
+ #
+ def escape: (string str) -> String
+
+ #
+ # Escape only the tags of certain HTML elements in `string`.
+ #
+ # Takes an element or elements or array of elements. Each element is specified
+ # by the name of the element, without angle brackets. This matches both the
+ # start and the end tag of that element. The attribute list of the open tag will
+ # also be escaped (for instance, the double-quotes surrounding attribute
+ # values).
+ #
+ # print CGI.escapeElement('
', "A", "IMG")
+ # # "
<A HREF="url"></A>"
+ #
+ # print CGI.escapeElement('
', ["A", "IMG"])
+ # # "
<A HREF="url"></A>"
+ #
+ def escapeElement: (string string, *String | Array[String] elements) -> String
+
+ #
+ # Escape special characters in HTML, namely '&"<>
+ # CGI.escapeHTML('Usage: foo "bar" ')
+ # # => "Usage: foo "bar" <baz>"
+ #
+ def escapeHTML: (string str) -> String
+
+ #
+ # URL-encode a string following RFC 3986 Space characters (+" "+) are encoded
+ # with (+"%20"+)
+ # url_encoded_string = CGI.escapeURIComponent("'Stop!' said Fred")
+ # # => "%27Stop%21%27%20said%20Fred"
+ #
+ def escapeURIComponent: (string) -> String
+
+ #
+ # Synonym for CGI.escapeElement(str)
+ #
+ alias escape_element escapeElement
+
+ #
+ # Synonym for CGI.escapeHTML(str)
+ #
+ alias escape_html escapeHTML
+
+ #
+ #
+ alias escape_uri_component escapeURIComponent
+
+ #
+ #
+ alias h escapeHTML
+
+ #
+ # URL-decode an application/x-www-form-urlencoded string with
+ # encoding(optional).
+ # string = CGI.unescape("%27Stop%21%27+said+Fred")
+ # # => "'Stop!' said Fred"
+ #
+ def unescape: (string str, ?encoding encoding) -> String
+
+ #
+ # Undo escaping such as that done by CGI.escapeElement()
+ #
+ # print CGI.unescapeElement(
+ # CGI.escapeHTML('
'), "A", "IMG")
+ # # "<BR>"
+ #
+ # print CGI.unescapeElement(
+ # CGI.escapeHTML('
'), ["A", "IMG"])
+ # # "<BR>"
+ #
+ def unescapeElement: (string string, *String | Array[String] elements) -> String
+
+ #
+ # Unescape a string that has been HTML-escaped
+ # CGI.unescapeHTML("Usage: foo "bar" <baz>")
+ # # => "Usage: foo \"bar\" "
+ #
+ def unescapeHTML: (string str) -> String
+
+ #
+ # URL-decode a string following RFC 3986 with encoding(optional).
+ # string = CGI.unescapeURIComponent("%27Stop%21%27+said%20Fred")
+ # # => "'Stop!'+said Fred"
+ #
+ def unescapeURIComponent: (string) -> String
+
+ #
+ # Synonym for CGI.unescapeElement(str)
+ #
+ alias unescape_element unescapeElement
+
+ #
+ # Synonym for CGI.unescapeHTML(str)
+ #
+ alias unescape_html unescapeHTML
+
+ #
+ #
+ alias unescape_uri_component unescapeURIComponent
+ end
+end
diff --git a/stdlib/cgi/0/core.rbs b/stdlib/cgi/0/core.rbs
index ac62d42c0..4c563f0de 100644
--- a/stdlib/cgi/0/core.rbs
+++ b/stdlib/cgi/0/core.rbs
@@ -637,88 +637,6 @@ class CGI
| (Hash[String, untyped] options_hash) -> void
end
- #
- # Escape/unescape for CGI, HTML, URI.
- #
- module Escape
- #
- # URL-encode a string into application/x-www-form-urlencoded. Space characters
- # (+" "+) are encoded with plus signs (+"+"+)
- # url_encoded_string = CGI.escape("'Stop!' said Fred")
- # # => "%27Stop%21%27+said+Fred"
- #
- def escape: (string str) -> String
-
- #
- # Escape special characters in HTML, namely '&"<>
- # CGI.escapeHTML('Usage: foo "bar" ')
- # # => "Usage: foo "bar" <baz>"
- #
- def escapeHTML: (string str) -> String
-
- #
- # URL-encode a string following RFC 3986 Space characters (+" "+) are encoded
- # with (+"%20"+)
- # url_encoded_string = CGI.escapeURIComponent("'Stop!' said Fred")
- # # => "%27Stop%21%27%20said%20Fred"
- #
- def escapeURIComponent: (string) -> String
-
- #
- #
- alias escape_uri_component escapeURIComponent
-
- #
- # URL-decode an application/x-www-form-urlencoded string with
- # encoding(optional).
- # string = CGI.unescape("%27Stop%21%27+said+Fred")
- # # => "'Stop!' said Fred"
- #
- def unescape: (string str, ?encoding encoding) -> String
-
- #
- # Unescape a string that has been HTML-escaped
- # CGI.unescapeHTML("Usage: foo "bar" <baz>")
- # # => "Usage: foo \"bar\" "
- #
- def unescapeHTML: (string str) -> String
-
- #
- # URL-decode a string following RFC 3986 with encoding(optional).
- # string = CGI.unescapeURIComponent("%27Stop%21%27+said%20Fred")
- # # => "'Stop!'+said Fred"
- #
- def unescapeURIComponent: (string) -> String
-
- #
- #
- alias unescape_uri_component unescapeURIComponent
- end
-
#
# Exception raised when there is an invalid encoding detected
#
@@ -935,45 +853,6 @@ class CGI
end
module Util
- include CGI::Escape
-
- #
- # Escape only the tags of certain HTML elements in `string`.
- #
- # Takes an element or elements or array of elements. Each element is specified
- # by the name of the element, without angle brackets. This matches both the
- # start and the end tag of that element. The attribute list of the open tag will
- # also be escaped (for instance, the double-quotes surrounding attribute
- # values).
- #
- # print CGI.escapeElement('
', "A", "IMG")
- # # "
<A HREF="url"></A>"
- #
- # print CGI.escapeElement('
', ["A", "IMG"])
- # # "
<A HREF="url"></A>"
- #
- def escapeElement: (string string, *String | Array[String] elements) -> String
-
- #
- # Synonym for CGI.escapeElement(str)
- #
- alias escape_element escapeElement
-
- #
- # Synonym for CGI.escapeHTML(str)
- #
- alias escape_html escapeHTML
-
- #
- #
- alias h escapeHTML
-
#
- # Undo escaping such as that done by CGI.escapeElement()
- #
- # print CGI.unescapeElement(
- # CGI.escapeHTML('
'), "A", "IMG")
- # # "<BR>"
- #
- # print CGI.unescapeElement(
- # CGI.escapeHTML('
'), ["A", "IMG"])
- # # "<BR>"
- #
- def unescapeElement: (string string, *String | Array[String] elements) -> String
-
- #
- # Synonym for CGI.unescapeElement(str)
- #
- alias unescape_element unescapeElement
-
- #
- # Synonym for CGI.unescapeHTML(str)
- #
- alias unescape_html unescapeHTML
-
# Abbreviated day-of-week names specified by RFC 822
RFC822_DAYS: Array[String]
diff --git a/stdlib/cgi/0/manifest.yaml b/stdlib/cgi/0/manifest.yaml
index f97f1bdf5..c43126c47 100644
--- a/stdlib/cgi/0/manifest.yaml
+++ b/stdlib/cgi/0/manifest.yaml
@@ -1,3 +1,4 @@
dependencies:
- name: tempfile
- name: stringio
+ - name: cgi-escape
diff --git a/test/stdlib/CGI-escape_test.rb b/test/stdlib/CGI-escape_test.rb
new file mode 100644
index 000000000..642000742
--- /dev/null
+++ b/test/stdlib/CGI-escape_test.rb
@@ -0,0 +1,31 @@
+require_relative "test_helper"
+require "cgi"
+
+class CGI__EscapeSingletonTest < Test::Unit::TestCase
+ include TestHelper
+
+ library "cgi-escape"
+ testing "singleton(::CGI)"
+
+ def test_escapeURIComponent
+ assert_send_type(
+ "(String) -> String",
+ CGI, :escapeURIComponent, "hogehoge"
+ )
+ assert_send_type(
+ "(ToStr) -> String",
+ CGI, :escapeURIComponent, ToStr.new("hogehoge")
+ )
+ end
+
+ def test_unescapeURIComponent
+ assert_send_type(
+ "(String) -> String",
+ CGI, :unescapeURIComponent, "hogehoge"
+ )
+ assert_send_type(
+ "(ToStr) -> String",
+ CGI, :unescapeURIComponent, ToStr.new("hogehoge")
+ )
+ end
+end
diff --git a/test/stdlib/CGI_test.rb b/test/stdlib/CGI_test.rb
deleted file mode 100644
index dfdff203b..000000000
--- a/test/stdlib/CGI_test.rb
+++ /dev/null
@@ -1,134 +0,0 @@
-require_relative "test_helper"
-require "cgi"
-
-class CGISingletonTest < Test::Unit::TestCase
- include TestHelper
-
- library "cgi"
- testing "singleton(::CGI)"
-
- def test_escapeURIComponent
- assert_send_type(
- "(String) -> String",
- CGI, :escapeURIComponent, "hogehoge"
- )
- assert_send_type(
- "(ToStr) -> String",
- CGI, :escapeURIComponent, ToStr.new("hogehoge")
- )
- end
-
- def test_unescapeURIComponent
- assert_send_type(
- "(String) -> String",
- CGI, :unescapeURIComponent, "hogehoge"
- )
- assert_send_type(
- "(ToStr) -> String",
- CGI, :unescapeURIComponent, ToStr.new("hogehoge")
- )
- end
-
- # These methods are removed in Ruby 3.5.
- unless RUBY_VERSION >= "3.5"
- def test_new
- ARGV.replace(%w(abc=001 def=002))
- assert_send_type "() -> void",
- CGI, :new
-
- assert_send_type "(?::String options) -> void",
- CGI, :new, 'html3'
- assert_send_type "(?::String options) ?{ (::String name, ::String value) -> void } -> void",
- CGI, :new, 'html3' do |name, value| name + value end
- assert_send_type "(::Hash[::Symbol, untyped] options_hash) -> void",
- CGI, :new, { tag_maker: 'html5', max_multipart_length: 2048 }
- assert_send_type "(::Hash[::Symbol, untyped] options_hash) ?{ (::String name, ::String value) -> void } -> void",
- CGI, :new, { tag_maker: 'html5', max_multipart_length: 2048 } do |name, value| name + value end
- end
-
- def test_accept_charset
- assert_send_type "() -> ::encoding",
- CGI, :accept_charset
- end
-
- def test_accept_charset=
- assert_send_type "(::String accept_charset) -> ::String",
- CGI, :accept_charset=, 'utf-8'
- assert_send_type "(::Encoding accept_charset) -> ::Encoding",
- CGI, :accept_charset=, Encoding::UTF_8
- end
-
- def test_parse
- assert_send_type "(::String query) -> ::Hash[::String, String | Array[String]]",
- CGI, :parse, 'a=hoge&b=1&c[]=test1&c[]=test2'
- end
- end
-end
-
-class CGITest < Test::Unit::TestCase
- include TestHelper
-
- library "cgi"
- testing "::CGI"
-
- def setup
- super
- ARGV.replace(%w(abc=001 def=002))
- end
-
- def test_print
- assert_send_type "(*::String options) -> void",
- CGI.new, :print, ''
- end
-
- # These methods are removed in Ruby 3.5.
- unless RUBY_VERSION >= "3.5"
- def test_http_header
- assert_send_type "() -> ::String",
- CGI.new, :http_header
- assert_send_type "(::String options) -> ::String",
- CGI.new, :http_header, 'text/csv'
- assert_send_type "(::Hash[::String, untyped] header_hash) -> ::String",
- CGI.new, :http_header, { 'type' => 'text/csv', 'nph' => false, 'length' => 1024 }
- assert_send_type "(::Hash[::Symbol, untyped] header_hash) -> ::String",
- CGI.new, :http_header, { type: 'text/csv', nph: false, length: 1024 }
- end
-
- def test_header
- assert_send_type "() -> ::String",
- CGI.new, :header
- assert_send_type "(::String options) -> ::String",
- CGI.new, :header, 'text/csv'
- assert_send_type "(::Hash[::String, untyped] header_hash) -> ::String",
- CGI.new, :header, { 'type' => 'text/csv', 'nph' => false, 'length' => 1024 }
- assert_send_type "(::Hash[::Symbol, untyped] header_hash) -> ::String",
- CGI.new, :header, { type: 'text/csv', nph: false, length: 1024 }
- end
-
- def test_nph?
- assert_send_type "() -> ::boolish",
- CGI.new, :nph?
- end
-
- def test_out
- assert_send_type "() { () -> void } -> void",
- CGI.new, :out do '' end
- assert_send_type "(::String content_type_string) { () -> String } -> void",
- CGI.new, :out, 'text/csv' do '' end
- assert_send_type "(::Hash[::String, untyped] header_hash) { () -> String } -> void",
- CGI.new, :out, { 'type' => 'text/csv', 'nph' => false, 'length' => 1024 } do '' end
- assert_send_type "(::Hash[::String | ::Symbol, untyped] header_hash) { () -> String } -> void",
- CGI.new, :out, { type: 'text/csv' } do '' end
- end
-
- def test_stdinput
- assert_send_type "() -> ::IO",
- CGI.new, :stdinput
- end
-
- def test_stdoutput
- assert_send_type "() -> ::IO",
- CGI.new, :stdoutput
- end
- end
-end